web-dev-qa-db-fra.com

Comment capturer un événement "fin de réponse" dans node.js + express?

Je voudrais écrire une fonction middleware express qui configure un écouteur sur l'événement 'end' de la réponse, s'il en existe un. Le but est de faire un nettoyage basé sur le code de réponse http que le gestionnaire final a décidé d'envoyer, par ex. journalisation du code de réponse et annulation/validation d'une transaction db. c'est-à-dire que je veux que ce nettoyage soit transparent pour l'appelant final.

Je voudrais faire quelque chose comme ce qui suit en express:

L'intergiciel de route

function (req, res, next) {
   res.on ('end', function () {
      // log the response code and handle db
      if (res.statusCode < 400) { db.commit() } else { db.rollback() }
   });
   next();
}

La route:

app.post ("/something", function (req, res) { 
    db.doSomething (function () {
       if (some problem) {
          res.send (500);
       } else {
          res.send (200);
       }
    });
 }

Lorsque j'essaie, le gestionnaire d'événements "end" n'est jamais appelé. De même pour res.on('close'), que j'ai lu dans un autre article. Ces événements sont-ils renvoyés?

La seule autre façon dont je peux penser à faire cela est d'encapsuler res.end Ou res.send Avec ma propre version dans un middleware personnalisé. Ce n'est pas idéal, car res.end Et res.send Ne prennent pas de rappels, donc je ne peux pas simplement les encapsuler, appeler l'original et ensuite faire mon truc en fonction du code de réponse qui a été défini quand ils me rappellent (parce qu'ils ne me rappelleront pas).

Existe-t-il un moyen simple de procéder?

34
Jake

En lisant documentation , voici la signature de res.send:

res.send(body|status[, headers|status[, status]])

Ce qui signifie que vous pouvez définir votre propre statut, comme ceci: res.send( 'some string', 200 ); ou même simplement res.send( 404 );.

Cette méthode est celle que vous utilisez pour envoyer la réponse.

Une fois qu'il est envoyé au client, vous ne pouvez plus y accéder, il n'y a donc pas de rappel.

C'est la dernière chose que fait votre serveur. Une fois qu'il a traité la demande, il envoie la réponse.

Cependant, vous pouvez y accéder avant vous l'envoyez au client. Cela signifie que vous pouvez:

console.log( res );
res.send( datas );

Si vous souhaitez annuler/valider, vous le faites lorsque le rappel de la base de données est appelé, pas lorsque la réponse a disparu.

2
Florian Margaine

Curieusement, il semble que la réponse émette un événement "finish" lorsque la réponse est fermée: http://sambro.is-super-awesome.com/2011/06/27/listening-for-end- of-response-with-nodeexpress-js /

Bien que cette entrée de blog soit un peu ancienne, cet événement existe toujours ( ligne 836 dans lib/http.js ), donc je suppose qu'il ne disparaîtra pas de si tôt, même si ni la documentation du nœud ni la mention expresse ne le mentionnent. il. Début 2014, il est passé à ligne 504 de lib/_http_outgoing.js et fonctionne toujours.

Soit dit en passant, l'événement "erreur" sur une réponse du serveur n'est probablement pas quelque chose que vous voudriez habituellement voir.

43
Aveius

Pour approfondir la réponse de @ Amatsuyu, voici à quoi cela devrait ressembler:

res.on('finish', function() {
  // do stuff here
});
30
dmon