Warum kann ich Code nach "res.send" ausführen?

78

Ich frage mich, welche Mechanismen hinter dem Verhalten des folgenden Codes stehen:

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

Mein Verständnis ist, dass die Funktion res.sendnicht zurückgegeben wird, sondern die Verbindung geschlossen / die Anforderung beendet wird . Dies könnte erklären, warum ich nach einem res.sendBefehl immer noch Code ausführen kann (ich habe die Express-Quelle durchgesehen und es scheint keine asynchrone Funktion zu sein).

Gibt es noch etwas im Spiel, das mir möglicherweise fehlt?

Leonidas
quelle
Entschuldigung, ich habe Ihren Beitrag falsch gelesen und war mir nicht sicher, was das Problem mit Ihrem Code war, da er absolut legitim ist. Wenn Sie es aufrufen send, leiten Sie einfach Daten über die http-Verbindung weiter und Ihr Code wird fortgesetzt. Sie können nur verwenden, returnwenn Sie den Code beenden oder einfach nichts anderes schreiben möchten. Entschuldigung für die Fehlinterpretation.
Timmerz

Antworten:

122

Sicher endbeendet die HTTP-Antwort, aber es hat nichts Besonderes mit Ihrem Code zu tun.

Sie können andere Dinge auch dann tun, wenn Sie eine Antwort beendet haben.

Was Sie jedoch nicht tun können, ist etwas Nützliches zu tun res. Da die Antwort beendet ist, können Sie keine weiteren Daten darauf schreiben.

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

Dieses Verhalten unterscheidet sich von anderen herkömmlichen Frameworks (PHP, ASP usw.), die einer HTTP-Anforderung einen Thread zuweisen und den Thread beenden, wenn die Antwort beendet ist. Wenn Sie eine äquivalente Funktion wie die von ASP aufrufen Response.End, wird der Thread beendet und Ihr Code wird nicht mehr ausgeführt. Im Knoten gibt es keinen Thread zum Stoppen. reqund es reswerden keine weiteren Ereignisse ausgelöst, aber der Code in Ihren Rückrufen kann weiterhin ausgeführt werden (solange nicht versucht wird, Methoden aufzurufen, für resdie eine gültige Antwort erforderlich ist, um geöffnet zu sein).

josh3736
quelle
7
Diese Antwort war sehr hilfreich und hat mich überzeugt, Nodejs aus ideologischen Gründen zu verlassen.
Jkatzer
31
@ jkatzer Ideologie ist schwach. Pragmatismus gewinnt.
Anatoly G
8
Denken Sie natürlich daran, dass Node nur eine Ausführungsumgebung ist. Wenn Sie expressjs verwenden, ist dies Ihr Webserver. Was Sie sagen, ist wie sich zu fragen, warum Apache weiter läuft, nachdem PHP eine Antwort zurückgegeben hat. Sie können entweder diese zusätzliche Kapazität verwenden, den Status der Antwort nach dem Senden protokollieren oder einige andere Anwendungsfunktionen ausführen, die Ihnen überlassen bleiben. Mit großer Kraft geht jedoch große Verantwortung
einher
11
@jkatzer - Ihre Aussage ist völlig verrückt und illustriert eine toxische Mentalität.
Der Dembinski
1
@AnatolyG Ich habe Ihren Kommentar mindestens 5 Mal gelesen, während ich diesen Kommentarbereich gelesen habe, und ich habe ihn jedes Mal als Plagiat gelesen und habe darüber gelacht, jetzt über mich. Lol.
Lalit Fauzdar
44

Bearbeiten: Ich mache nicht mehr das, was unten erklärt wird, da Sie keinen Wert zurückgeben sollten, wenn es nicht nötig ist. Es macht Ihren Code weniger lesbar und sieht hackisch aus. Stattdessen schlage ich vor, die return-Anweisung von der zu trennen res.send(). @slavafomin hat dies in den Kommentaren gut erklärt.

Eine einfache Möglichkeit, die Ausführung der Funktion zu stoppen und gleichzeitig eine Antwort zu senden, besteht darin, dies zu tun

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

Auf diese Weise können Sie kurze ifAnweisungen verwenden, um Fehler zu behandeln, z.

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

Die genaue Rückgabe der res.sendFunktion ist ein Objekt , das den gesamten Status der Verbindung nach dem Beenden zu enthalten scheint (Anforderung, Status, Header usw.). Dies sollte jedoch unwichtig sein, da Sie nichts damit tun.

Marcos Pereira
quelle
2
Dies ist ein großartiger Punkt, aber technisch nicht die Antwort. denn die Frage ist mehr über das Warum als das Wie. Trotzdem ein toller Beitrag, daher die positive Bewertung :).
Nepoxx
3
Ja, zu der Zeit konnte ich jedoch keinen Kommentar abgeben, also musste ich eine Antwort posten.
Marcos Pereira
4
Ich würde davon abraten, diese Technik zu verwenden. Es verkürzt den Code, macht ihn aber auch weniger aussagekräftig und vage, da es eine falsche Semantik verwendet. Wenn Sie den Wert aus der Funktion nicht verwenden, sollten Sie keinen zurückgeben. Außerdem können typisiertes JavaScript (wie TypeScript) und Tools mithilfe der statischen Code-Analyse beschädigt werden. Mit anderen Worten: Es sieht hackisch und unprofessionell aus.
Slava Fomin II
1
@SlavaFominII Es kann so sein: res.send('500', 'Error message here');return;inside- ifAnweisung.
Ali Sherafat
@SlavaFominll Ich denke, diese Methode ist so verbreitet, dass man sie nicht mehr als hackisch bezeichnen kann. Was statische Analysegeräte betrifft - da Expressentwickler die Retouren dieser Funktion verarbeiten, bin ich mir ziemlich sicher, dass es nicht viel zu befürchten gibt. Sind Sie auf ein bestimmtes Problem gestoßen?
Ohad Cohen