Maison  >  Article  >  interface Web  >  Explication détaillée de l'utilisation de la fonction suivante dans express dans nodejs

Explication détaillée de l'utilisation de la fonction suivante dans express dans nodejs

巴扎黑
巴扎黑original
2017-09-09 09:54:252217parcourir

Cet article présente principalement la compréhension de nodejs de la fonction suivante dans express, qui a une certaine valeur de référence. Les amis intéressés peuvent s'y référer

Récemment, l'entreprise a utilisé node pour séparer le front-end et le back-end. Le framework web utilisé est express, j'ai donc une compréhension approfondie du framework express. J'ai écrit un article sur le routage express il y a quelque temps, mais il semble qu'il manque un contenu très important dans cet article, qui est le prochain d'express. , alors aujourd'hui, parlons séparément du prochain express.

Je vais expliquer next principalement à partir de trois points :

  • Quel est le rôle de next ?

  • Quand devrions-nous l'utiliser ensuite ?

  • Quel est le mécanisme de mise en œuvre interne de next ?

Le rôle de Next

Lorsque nous définirons la fonction middleware express, nous définirons le troisième paramètre comme next, et ce next est notre Protagoniste d'aujourd'hui, la fonction next est principalement responsable de transmettre le contrôle au middleware suivant. Si le middleware actuel ne termine pas la requête et que le suivant n'est pas appelé, alors la requête sera suspendue et le middleware défini ultérieurement ne sera pas exécuté.

Quand utiliser Next

D'après la description ci-dessus, nous savons déjà que la fonction suivante est principalement utilisée pour garantir que tous les middlewares enregistrés sont exécutés un par un, puis Nous devrions appeler la fonction suivante dans tous les middlewares, mais il existe un cas particulier. Si le middleware que nous définissons termine cette requête, alors la fonction suivante ne doit pas être appelée à nouveau, sinon des problèmes pourraient survenir. Regardons cette section. 🎜>


app.get('/a', function(req, res, next) {
  res.send('sucess');
  next();
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
 console.log(404);
 var err = new Error('Not Found');
 err.status = 404;
 next(err);
});

app.use(function(err, req, res, next) {
 res.status(err.status || 500);
 res.render('error', {
  message: err.message,
  error: {}
 });
});
envoie la requête "/a", et la console imprime le journal comme suit :


404
GET /a 500 6.837 ms - -
Error: Can't set headers after they are sent.
  at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:345:11)
Pourquoi le code lève-t-il une exception ? C'est parce que nous avons appelé la fonction suivante après res.send. Bien que notre requête ait été terminée, le middleware 404 suivant sera toujours exécuté et le middleware suivant essaiera d'accéder à res. ​​aux en-têtes, donc l'exception ci-dessus sera levée.

Vous aurez peut-être une question après avoir lu ceci. Si je n'appelle pas la fonction suivante après res.send, le middleware 404 défini plus tard ne sera-t-il jamais exécuté ? Maintenant, nous supprimons le prochain appel de fonction après res.send et envoyons la requête "/xxx", nous constaterons que le middleware 404 est exécuté, (ㄒoㄒ), n'est-ce pas contradictoire avec ce que nous avons dit précédemment, notre personnalisation Le le middleware n'appelle pas ensuite, mais le middleware défini plus tard est toujours exécuté. Pourquoi ? Il semble que nous ne pouvons demander de l'aide qu'au code source~~~

Le mécanisme interne de Next


function next(err) {
  ... //此处源码省略
  // find next matching layer
  var layer;
  var match;
  var route;

  while (match !== true && idx < stack.length) {
   layer = stack[idx++];
   match = matchLayer(layer, path);
   route = layer.route;

   if (typeof match !== &#39;boolean&#39;) {
    // hold on to layerError
    layerError = layerError || match;
   }

   if (match !== true) {
    continue;
   }
   ... //此处源码省略
  }
 ... //此处源码省略
  // this should be done for the layer
  if (err) {
    layer.handle_error(err, req, res, next);
  } else {
   layer.handle_request(req, res, next);
  }
 }
Le ci-dessus est le suivant dans express Le code source a été supprimé pour faciliter l'explication du problème. À partir du code source ci-dessus, nous pouvons constater qu'il y a une boucle while à l'intérieur de la fonction suivante. Chaque boucle supprimera une couche de la pile. Cette couche contient des informations de routage et de middleware, puis la couche sera utilisée pour correspondre à celle demandée. chemin. Si la correspondance réussit, layer.handle_request sera exécuté et la fonction middleware sera appelée. Mais si la correspondance échoue, la couche suivante (c'est-à-dire le middleware) sera bouclée.

Nous pouvons maintenant expliquer le problème soulevé ci-dessus, pourquoi la fonction suivante n'est pas appelée dans notre middleware personnalisé, mais le middleware 404 suivant sera toujours exécuté car nous avons demandé "/xxx" Le middleware de routage "/a" nous avons enregistré ne peut pas correspondre, donc la boucle while continuera à s'exécuter. Le middleware 404 correspondant est réussi, donc le middleware 404 sera exécuté.

Remarque : Pour les middlewares enregistrés avec app.use, si le paramètre path est vide, sa valeur par défaut est "/", et le middleware avec le chemin "/" correspond à toutes les requêtes par défaut.

Une chose est à souligner en particulier. En effet, lorsque l'on définit un middleware de routage, le troisième paramètre next de la fonction n'est pas le même next que le troisième paramètre next de la fonction lorsque l'on définit le non-. Ce que vous voyez ci-dessus est la prochaine fonction du middleware sans routage, et la fonction suivante du middleware de routage est comme celle-ci


function next(err) {
  if (err && err === &#39;route&#39;) {
   return done();
  }

  var layer = stack[idx++];
  if (!layer) {
   return done(err);
  }

  if (layer.method && layer.method !== method) {
   return next(err);
  }

  if (err) {
   layer.handle_error(err, req, res, next);
  } else {
   layer.handle_request(req, res, next);
  }
 }
Cette suivante est beaucoup plus simple que. celui ci-dessus. Il est chargé de passer le contrôle de plusieurs middlewares de la même route, et il recevra un paramètre "route". Si next("route") est appelé, il ignorera les autres middlewares de la route actuelle et directement. transférer le contrôle à l'itinéraire suivant.

Enfin, il est nécessaire de parler de next(err). Comment next(err) transfère le contrôle au middleware de gestion des erreurs. D'après le code précédent, nous savons que lorsque next(err) est appelé, la couche express. .handle_error sera appelé en interne, jetons donc un œil à son code source


Layer.prototype.handle_error = function handle_error(error, req, res, next) {
 var fn = this.handle;

 if (fn.length !== 4) {
  // not a standard error handler
  return next(error);
 }

 try {
  fn(error, req, res, next);
 } catch (err) {
  next(err);
 }
};
Le fn dans le code est la fonction middleware, et express déterminera le numéro des paramètres de fn Faites un jugement. Si le nombre de paramètres n'est pas égal à 4, cela n'est pas considéré comme un middleware de gestion des erreurs, puis continuez à appeler next(err). Cela entrera dans la fonction middleware suivante et continuera à juger. nombre de paramètres. De cette façon jusqu'à un certain Si le nombre de paramètres de la fonction middleware est de 4, on considère que le middleware de gestion des erreurs est trouvé, puis la fonction middleware est exécutée.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn