95 votes

Pourquoi puis-je exécuter du code après "res.send" ?

Je me demande quelle est la mécanique derrière le comportement du code suivant :

res.send(200, { data: 'test data' });
console.log('still here...');

Je crois savoir que res.send n'a pas retourner la fonction, mais ne fermer la connexion / terminer la demande . Cela pourrait expliquer pourquoi je peux toujours exécuter du code après une erreur d'écriture. res.send (j'ai regardé dans la source express et il ne semble pas que ce soit une fonction asynchrone).

Y a-t-il quelque chose d'autre en jeu que je pourrais manquer ?

147voto

josh3736 Points 41911

Bien sûr end termine la réponse HTTP, mais ne fait rien de spécial à votre code.

Vous pouvez continuer à faire d'autres choses même après avoir terminé une réponse.

Ce que vous ne peut pas ne fait, cependant, rien d'utile avec res . Comme la réponse est terminée, vous ne pouvez plus y écrire de données.

res.send(...);
res.write('more stuff'); // throws an error since res is now closed

Ce comportement est différent des autres frameworks traditionnels (PHP, ASP, etc.) qui allouent un thread à une requête HTTP et terminent le thread lorsque la réponse est terminée. Si vous appelez une fonction équivalente comme la fonction ASP Response.End le thread se termine et votre code cesse de s'exécuter. Dans node, il n'y a pas de thread à arrêter. req y res ne déclenchera plus d'événements, mais le code dans vos callbacks est libre de continuer à s'exécuter (tant qu'il n'essaie pas d'appeler des méthodes sur res qui nécessitent une réponse valide pour être ouverts).

51voto

marcospgp Points 741

Edita: Je ne fais plus ce qui est expliqué ci-dessous, car il ne faut pas retourner une valeur quand on n'en a pas besoin. Cela rend votre code moins lisible et ressemble à du bricolage. À la place, je suggère de séparer l'instruction de retour de la fonction res.send() . @slavafomin l'a bien expliqué dans les commentaires.

Une façon simple d'arrêter l'exécution de la fonction et d'envoyer une réponse en même temps est de faire

return res.send('500', 'Error message here');

Cela vous permet d'utiliser de courtes if pour gérer les erreurs telles que :

if (err) {
    return res.send('500', 'Error message here');
}

L'exact retourner de la res.send est une fonction objet que semble contenir l'état complet de la connexion après que vous l'ayez terminée. (requête, statut, en-têtes, etc.), mais cela devrait être sans importance puisque vous n'en ferez rien.

0voto

Boris Yakubchik Points 564

Une solution possible est cette bibliothèque : sur-fini

var destroy = require('destroy')
var fs = require('fs')
var http = require('http')
var onFinished = require('on-finished')

http.createServer(function onRequest (req, res) {
  var stream = fs.createReadStream('package.json')
  stream.pipe(res)
  onFinished(res, () => {
    destroy(stream)
  })
})

Fonctionne avec Express aussi, par exemple :

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

app.get('/video', (req, res) => {
 const ffmpeg = spawn(ffmpegPath, argsArray);
 ffmpeg.stdout.pipe(res);
 onFinished(res, () => {
   ffmpeg.kill();
 });
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X