Fonction suivante Express, à quoi ça sert vraiment?


124

J'ai essayé de trouver une bonne description de ce que fait la next()méthode. Dans la documentation Express, il est indiqué que cela next('route')peut être utilisé pour sauter sur cette route et ignorer toutes les routes intermédiaires, mais nextest parfois appelée sans arguments. Quelqu'un connaît un bon tutoriel, etc. qui décrit la nextfonction?

Réponses:


161

next()sans arguments dit "je plaisante, je ne veux pas vraiment gérer ça". Il revient et essaie de trouver le prochain itinéraire qui correspondrait.

Ceci est utile, par exemple si vous voulez avoir une sorte de gestionnaire de pages avec des slugs d'url, ainsi que beaucoup d'autres choses, mais voici un exemple.

app.get('/:pageslug', function(req, res, next){
  var page = db.findPage(req.params.pageslug);
  if (page) {
    res.send(page.body);
  } else {
    next();
  }
});

app.get('/other_routes', function() {
  //...
});

Ce code composé devrait vérifier une base de données pour une page avec un certain slug d'ID. S'il en trouve un, rendez-le! s'il n'en trouve pas, ignorez ce gestionnaire de route et recherchez d'autres.

Donc, next()sans argument, cela permet de prétendre que vous n'avez pas géré l'itinéraire afin que quelque chose d'autre puisse le récupérer à la place.


Ou un compteur de succès avec app.all('*'). Ce qui vous permet d'exécuter du code de configuration partagé, puis de passer à d'autres routes pour faire quelque chose de plus spécifique.

app.all('*', function(req, res, next){
  myHitCounter.count += 1;
  next();
});

app.get('/other_routes', function() {
  //...
});

Très bonne réponse! J'ai également vu d'autres utilisations de next, par exemple next (err) et next ('route'). En avez-vous maintenant le but, quand souhaitez-vous propager une erreur et quand souhaitez-vous passer à un certain itinéraire?
Andreas Selenwall

8
@AndreasSelenwall next('route')est spécifique à app.VERB()et est utilisé lorsqu'une route a plusieurs rappels pour " contourner le (s) rappel (s) de route restants. " next(err)Est utilisé pour passer à n'importe quel " middleware d'erreur " (à Epartir de la publication).
Jonathan Lonowski

5
Vote positif. Juste pour cette phrase: "je plaisante, je ne veux pas vraiment gérer ça" vous m'avez fait comprendre ce que je cherchais. J'ai vu beaucoup de questions similaires et j'ai trouvé une solution en une phrase.
Pedro Barros

8
L'appel next()sans argument ne dit pas vraiment au système "je ne veux pas gérer ça", il dit simplement au système de continuer à traiter les middlewares restants après celui-ci. Ce n'est pas une condition d'erreur à appeler next(), cela fait partie du flux normal. Si vous n'appelez pas, next()aucune autre route ne sera traitée du tout.
d512

1
Je souhaite que plus de réponses sur ce site Web aient été écrites pour le profane ... 'next () sans arguments dit "je plaisante, je ne veux pas vraiment gérer ça"' - Parfait pour les noobs ... (@ d512 a un meilleure explication cependant)
daCoda

129

Dans la plupart des frameworks, vous recevez une requête et vous souhaitez renvoyer une réponse. En raison de la nature asynchrone de Node.js, vous rencontrez des problèmes avec les rappels imbriqués si vous faites des choses non triviales. Pour éviter que cela ne se produise, Connect.js (avant la v4.0, Express.js était une couche au-dessus de connect.js) a quelque chose qui s'appelle middleware qui est une fonction avec 2, 3 ou 4 paramètres.

function (<err>, req, res, next) {}

Votre application Express.js est une pile de ces fonctions.

entrez la description de l'image ici

Le routeur est spécial, c'est un middleware qui vous permet d'exécuter un ou plusieurs middleware pour une certaine URL. C'est donc une pile à l'intérieur d'une pile.

Alors, que fait ensuite? Simple, il indique à votre application d'exécuter le prochain middleware. Mais que se passe-t-il lorsque vous passez quelque chose au suivant? Express abandonnera la pile actuelle et exécutera tout le middleware qui a 4 paramètres.

function (err, req, res, next) {}

Ce middleware est utilisé pour traiter les erreurs. J'aime faire ce qui suit:

next({ type: 'database', error: 'datacenter blew up' });

Avec cette erreur, je dirais probablement à l'utilisateur que quelque chose s'est mal passé et enregistrerais l'erreur réelle.

function (err, req, res, next) {
   if (err.type === 'database') {
     res.send('Something went wrong user');
     console.log(err.error);
   }
};

Si vous imaginez votre application Express.js comme une pile, vous pourrez probablement résoudre vous-même beaucoup de bizarreries. Par exemple, lorsque vous ajoutez votre middleware Cookie après votre routeur, il est logique que vos routes ne contiennent pas de cookies.


3
Où stockeriez-vous cette fonction de journalisation anonyme?
dennismonsewicz

"Express abandonnera la pile actuelle et exécutera tout le middleware qui a 4 paramètres." Je me demandais comment express est capable d'exécuter des middlewares de gestionnaire d'erreur exacts. Merci!
Abhishek Agarwal le

75

À mon humble avis, la réponse acceptée à cette question n'est pas vraiment précise. Comme d'autres l'ont dit, il s'agit vraiment de contrôler le moment où le prochain gestionnaire de la chaîne est exécuté. Mais je voulais fournir un peu plus de code pour le rendre plus concret. Disons que vous avez cette application express simple:

var express = require('express');
var app = express();

app.get('/user/:id', function (req, res, next) {
    console.log('before request handler');
    next();
});

app.get('/user/:id', function (req, res, next) {
    console.log('handling request');
    res.sendStatus(200);
    next();
});

app.get('/user/:id', function (req, res, next) {
    console.log('after request handler');
    next();
});

app.listen(3000, function () {
    console.log('Example app listening on port 3000!')
});

Si tu fais

curl http://localhost:3000/user/123

vous verrez ceci imprimé sur la console:

before request handler
handling request
after request handler

Maintenant, si vous commentez l'appel à next()dans le gestionnaire du milieu comme ceci:

app.get('/user/:id', function (req, res, next) {
    console.log('handling request');
    res.sendStatus(200);
    //next();
});

Vous verrez ceci sur la console:

before request handler
handling request

Notez que le dernier gestionnaire (celui qui imprime after request handler) ne s'exécute pas. C'est parce que vous ne dites plus à express d'exécuter le prochain gestionnaire.

Donc, peu importe si votre gestionnaire "principal" (celui qui renvoie 200) a réussi ou non, si vous voulez que le reste des middlewares s'exécute, vous devez appeler next().

Quand cela serait-il utile? Supposons que vous souhaitiez enregistrer toutes les demandes qui sont arrivées dans une base de données, que la demande ait réussi ou non.

app.get('/user/:id', function (req, res, next) {
    try {
       // ...
    }
    catch (ex) {
       // ...
    }
    finally {
       // go to the next handler regardless of what happened in this one
       next();
    }
});

app.get('/user/:id', function (req, res, next) {
    logToDatabase(req);
    next();
});

Si vous voulez que le deuxième gestionnaire s'exécute, vous devez appeler next()le premier gestionnaire.

Rappelez-vous que le nœud est asynchrone, il ne peut donc pas savoir quand le rappel du premier gestionnaire est terminé. Vous devez le dire en appelant next().


Sonfar la meilleure réponse pour moi.
Norayr Ghukasyan du

Eh bien explication!
Chang

7

next () sans paramètre invoque le prochain gestionnaire de route OU le middleware suivant dans le framework.


2
Ou le prochain middleware.
robertklep

1

Cela signifie simplement passer le contrôle au prochain gestionnaire.

À votre santé


1

Notez l'appel ci-dessus à next (). L'appel de cette fonction appelle la fonction middleware suivante dans l'application. La fonction next () ne fait pas partie de Node.js ou de l'API Express, mais est le troisième argument qui est passé à la fonction middleware. La fonction next () peut être nommée n'importe quoi, mais par convention, elle est toujours nommée «next». Pour éviter toute confusion, utilisez toujours cette convention.


0

Question également posée sur l'utilisation de la prochaine ('route') qui semble être couverte la semaine dans les réponses fournies jusqu'à présent:

  1. UTILISATION DE suivant ():

En bref: la prochaine fonction middleware.

Extrait de cette documentation officielle d' Express JS - page 'writing-middleware' :

"La fonction middleware myLogger imprime simplement un message, puis transmet la requête à la fonction middleware suivante de la pile en appelant la fonction next ()."

var express = require('express')
var app = express()

var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

app.use(myLogger)

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000)

Cette page de la documentation d'Express JS indique "Si la fonction middleware actuelle ne termine pas le cycle requête-réponse, elle doit appeler next () pour passer le contrôle à la fonction middleware suivante. Sinon, la requête sera laissée en suspens."

  1. UTILISATION DE next ('route'):

En bref: route suivante (vs fonction middleware suivante en cas de next ())

Extrait de cette documentation Express JS - page 'using-middleware' :

"Pour ignorer le reste des fonctions middleware d'une pile middleware de routeur, appelez next ('route') pour passer le contrôle à la route suivante . REMARQUE: next ('route') ne fonctionnera que dans les fonctions middleware qui ont été chargées en utilisant le fonctions app.METHOD () ou router.METHOD ().

Cet exemple montre une sous-pile middleware qui gère les requêtes GET au chemin / user /: id. "

app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id === '0') next('route')
  // otherwise pass the control to the next middleware function in this stack
  else next()
}, function (req, res, next) {
  // render a regular page
  res.render('regular')
})

// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
  res.render('special')
})

0

next () est l'argument de rappel de la fonction middleware avec req, et res étant la requête http et les arguments de réponse à next dans le code ci-dessous.

app.get ('/', (req, res, next) => {next ()});

Donc next () appelle la fonction middleware passée. Si la fonction middleware actuelle ne termine pas le cycle requête-réponse, elle doit appeler next (), sinon la requête sera laissée en suspens et expirera.

next () fn doit être appelé dans chaque fonction middleware lorsque plusieurs fonctions middleware sont passées à app.use ou app.METHOD, sinon la fonction middleware suivante ne sera pas appelée (dans le cas où plus d'une fonction middleware est passée). Pour ne pas appeler les fonctions middleware restantes, appelez next ('route') dans la fonction middleware, après quoi aucune autre fonction middleware ne doit être appelée. Dans le code ci-dessous, fn1 sera appelé et fn2 sera également appelé, puisque next () est appelé dans fn1. Cependant, fn3 ne sera pas appelé, car next ('route') est appelé dans fn2.

app.get('/fetch', function fn1(req, res, next)  {
console.log("First middleware function called"); 
    next();
}, 
function fn2(req, res, next) {
    console.log("Second middleware function called"); 
    next("route");
}, 
function fn3(req, res, next) {
    console.log("Third middleware function will not be called"); 
    next();
})
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.