Wie finde ich heraus, welche Versprechen in Node.js UnhandledPromiseRejectionWarning nicht behandelt werden?

177

Node.js aus Version 7 hat asynchronen / wartenden syntaktischen Zucker für den Umgang mit Versprechungen, und jetzt wird in meinem Code häufig die folgende Warnung angezeigt:

(node:11057) UnhandledPromiseRejectionWarning: Unhandled promise 
rejection (rejection id: 1): ReferenceError: Error: Can't set headers 
after they are sent.
(node:11057) DeprecationWarning: Unhandled promise rejections are 
deprecated. In the future, promise rejections that are not handled 
will terminate the Node.js process with a non-zero exit code.

Leider gibt es keinen Hinweis auf die Linie, in der der Fang fehlt. Gibt es eine Möglichkeit, es zu finden, ohne jeden Try / Catch-Block zu überprüfen?

user1658162
quelle
Sie könnten die Bluebird-Versprechensbibliothek verwenden und sie würde Ihnen wahrscheinlich eine Stapelverfolgung geben.
jfriend00
3
Vielleicht unhandledRejectionhilft die Registrierung bei Node ? Siehe die Dokumente . Ihr Rückruf erhält das ErrorObjekt und das tatsächliche Promise, und ich glaube, das ErrorObjekt könnte eine Stapelverfolgung enthalten.
YSK
Wenn die beiden vorherigen Kommentare nicht helfen, Can't set headers after they are sent.sollten Sie einen Hinweis darauf erhalten, wo in Ihrem Code dies passieren könnte (dh irgendwo setzen Sie Header, nachdem die Header bereits gesendet worden wären - vermutlich aufgrund eines Mangels an Verständnis für asynchronen Code , aber das ist eine Vermutung)
Jaromanda X
Hallo, dass Nachrichten sicher helfen, herauszufinden, wo im Code der Fehler ist, übrigens ist es nicht so einfach, wie die Zeile zu kennen.
user1658162
1
@ jfriend00 Es stellte sich heraus, dass eine asynchrone Funktion einen Fehler auslöste - diese internen Knotenversprechen für asynchrone Funktionen verwenden Bluebird niemals, sodass Bluebird in diesem Szenario nicht hilft.
Adam Reis

Antworten:

297

unhandledRejectionProzessereignis anhören .

process.on('unhandledRejection', (reason, p) => {
  console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
  // application specific logging, throwing an error, or other logic here
});
cuixiping
quelle
35
Durch die Protokollierung error.stack(oder im obigen Beispiel reason.stack) erhalten Sie die vollständige Stapelverfolgung des Fehlers.
Adam Reis
Vielen Dank für das Setzen process.onund nicht server.onwie in so vielen anderen Beispielen, die ich gefunden habe
PhillipHolmes
9
Ich wünschte, ich könnte sagen, dass dies funktioniert hat, aber es funktioniert nicht. Ich bin auf Knoten 8.9.4.
ffxsam
2
Ich habe den obigen Code ausprobiert und wurde aus beiden Gründen undefiniert, und p? Irgendwelche Vorschläge? "Unhandled Ablehnung bei: Versprechen {Zustand: 'abgelehnt', Grund: undefiniert} Grund: undefiniert"
Jeremy
3
Ich habe diesen Code oben in meine Knotendatei eingefügt app.jsund leider wird nichts protokolliert. Knoten v10.13.0.
user1063287
71

Der richtige Weg, um eine vollständige Stapelverfolgung für nicht behandelte ES6-Promise-Ablehnungen anzuzeigen, besteht darin, Node.js mit dem --trace-warningsFlag auszuführen . Dies zeigt die vollständige Stapelverfolgung für jede Warnung an, ohne dass die Ablehnung aus Ihrem eigenen Code heraus abgefangen werden muss. Beispielsweise:

Knoten --trace-warnings app.js.

Stellen Sie sicher, dass das trace-warningsFlag vor dem Namen Ihrer .jsDatei steht! Andernfalls wird das Flag als Argument für Ihr Skript interpretiert und von Node.js selbst ignoriert.

Wenn Sie nicht behandelte Ablehnungen tatsächlich verarbeiten möchten (z. B. indem Sie sie protokollieren), möchten Sie möglicherweise unhandled-rejectionstattdessen mein Modul verwenden, das alle nicht behandelten Ablehnungen für jede wichtige Promises-Implementierung, die dies unterstützt, mit einem einzigen Ereignishandler abfängt.

Dieses Modul unterstützt Bläuling, ES6 Promises, Q, WhenJS, es6-promise, then/promiseund alles , was das entspricht jedes der nicht behandelte Ablehnung Spezifikationen (Einzelheiten in der Dokumentation).

Sven Slootweg
quelle
20
Die Verwendung von Knoten 7.8.0 und all dies gibt mir eine Stapelverfolgung für eine Reihe von internen Knotenmodulen. (Knoten: 10372) UnhandledPromiseRejectionWarning: Nicht behandelte Ablehnung von Versprechen (Ablehnungs-ID: 2): undefiniert bei emitWarning (intern / prozess / versprechen.js: 59: 21) bei emitPendingUnhandledRejections (intern / prozess / versprechen.js: 86: 11) bei prozess ._tickDomainCallback (intern / process / next_tick.js: 136: 7)
Will Lovett
3
Ich sehe keine Ausgabe, die zeigt, wo das Problem des nicht behandelten Versprechens liegt.
Jason Leach
Ich habe dies hinzugefügt, package.jsonum das Skript zu starten, und leider wurde nichts protokolliert. Knoten v10.13.0.
user1063287
1
@ user1063287 Stellen Sie sicher, dass sich das Flag an der richtigen Stelle in Ihrem Befehl befindet. Ich habe der Antwort gerade ein Update hinzugefügt, um zu betonen, dass es vor dem Skriptnamen stehen muss.
Sven Slootweg
2
Sie sehen sich wahrscheinlich die Stapelverfolgung der Verfallswarnung an, nicht den ursprünglichen nicht behandelten Fehler (der irgendwo über der Verfallswarnung liegen sollte ).
Sven Slootweg
7

Protokollierung mit Stack-Trace

Wenn Sie nach einer hilfreichen Fehlermeldung suchen. Versuchen Sie, dies zu Ihrer Knotendatei hinzuzufügen. Es sollte die vollständige Stapelverfolgung anzeigen, in der Ihr Absturz stattfindet.

process.on('unhandledRejection', (error, p) => {
  console.log('=== UNHANDLED REJECTION ===');
  console.dir(error.stack);
});
Joshuakcockrell
quelle
Der einzige funktionale Unterschied besteht darin, eine console.dir für die Stack-Eigenschaft des Fehlers auszuführen. Ein ziemlicher Unterschied in der Ausgabe im Vergleich zur akzeptierten Antwort.
Joshuakcockrell