Comment trouver les promesses non gérées dans Node.js UnhandledPromiseRejectionWarning?

177

Node.js de la version 7 a du sucre syntaxique async / await pour gérer les promesses et maintenant, dans mon code, l'avertissement suivant apparaît assez souvent:

(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.

Malheureusement, il n'y a aucune référence à la ligne où la capture est manquante. Existe-t-il un moyen de le trouver sans vérifier chaque bloc try / catch?

user1658162
la source
Vous pouvez utiliser la bibliothèque de promesses Bluebird et cela vous donnera probablement une trace de pile.
jfriend00
3
Peut-être que vous inscrire à l' unhandledRejectionévénement de Node vous aidera? Consultez la documentation . Votre rappel obtient l' Errorobjet et le réel Promise, et je pense que l' Errorobjet peut contenir une trace de pile.
YSK
Si les deux commentaires précédents ne vous aident pas, cela Can't set headers after they are sent.devrait vous donner une idée de l'endroit où cela pourrait se produire dans votre code (c'est-à-dire quelque part où vous définissez des en-têtes après que les en-têtes auraient déjà été envoyés - probablement à cause d'une mauvaise compréhension du code asynchrone , mais c'est une supposition)
Jaromanda X
salut que les messages aident à trouver où dans le code se trouve le bogue, btw ce n'est pas aussi facile que de connaître la ligne.
user1658162
1
@ jfriend00 Il s'avère que c'était une situation où une fonction asynchrone lançait une erreur - ces promesses de Node internes pour les fonctions asynchrones n'utilisent jamais Bluebird, donc avoir Bluebird n'aide pas dans ce scénario.
Adam Reis

Réponses:

298

écouter l' unhandledRejectionévénement du processus.

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
la source
35
La journalisation error.stack(ou dans l'exemple ci-dessus reason.stack) vous donne la trace complète de la pile de l'erreur.
Adam Reis
9
J'aimerais pouvoir dire que cela a fonctionné, mais ce n'est pas le cas. Je suis sur le nœud 8.9.4.
ffxsam
2
J'ai essayé le code ci-dessus et je n'ai pas été défini pour les deux raisons, et p? Aucune suggestion? "Rejet non géré à: Promise {état: 'rejeté', raison: undefined} raison: undefined"
Jeremy
1
J'ai essayé cela et cela a fonctionné comme un charme! J'ai résolu mon problème très rapidement.
smb
3
J'ai ajouté ce code en haut de mon app.jsfichier de nœud et rien n'est malheureusement enregistré. Node v10.13.0.
user1063287
71

La manière correcte d'afficher une trace de pile complète pour les rejets de promesse ES6 non gérés consiste à exécuter Node.js avec l' --trace-warningsindicateur. Cela affichera le stacktrace complet pour chaque avertissement, sans avoir à intercepter le rejet depuis votre propre code. Par exemple:

node --trace-warnings app.js

Assurez-vous que l' trace-warningsindicateur précède le nom de votre .jsfichier! Sinon, l'indicateur sera interprété comme un argument de votre script, et il sera ignoré par Node.js lui-même.

Si vous voulez réellement gérer les rejets non gérés (par exemple en les journalisant), vous pouvez utiliser mon unhandled-rejectionmodule à la place, qui intercepte tous les rejets non gérés pour chaque implémentation majeure de Promises qui le prend en charge, avec un seul gestionnaire d'événements.

Ce module supports Bluebird, Promesses ES6, Q, WhenJS, es6-promise, then/promiseet tout ce qui est conforme à l' une des spécifications de rejet (non gérées détails complets dans la documentation).

Sven Slootweg
la source
20
L'utilisation du nœud 7.8.0 et tout cela me donne une trace de pile pour un tas de modules de nœuds internes. (nœud: 10372) UnhandledPromiseRejectionWarning: Rejet de promesse non géré (identifiant de rejet: 2): non défini à emitWarning (interne / process / promises.js: 59: 21) à emitPendingUnhandledRejections (interne / process / promises.js: 86: 11) à process ._tickDomainCallback (internal / process / next_tick.js: 136: 7)
Will Lovett
3
Je ne vois aucune sortie indiquant où se trouve le problème de la promesse non gérée.
Jason Leach
J'ai ajouté ceci pour package.jsondémarrer le script et rien n'a été enregistré malheureusement. Node v10.13.0.
user1063287
1
@ user1063287 Assurez-vous que l'indicateur est à la bonne place dans votre commande. Je viens d' ajouter une mise à jour à la réponse, à souligner qu'il a besoin d'aller avant le nom du script.
Sven Slootweg
2
Vous regardez probablement la trace de la pile de l'avertissement d'obsolescence, pas de l'erreur non gérée d'origine (qui devrait être quelque part au - dessus de l'avertissement d'obsolescence).
Sven Slootweg
7

Journalisation avec trace de pile

Si vous recherchez plus d'un message d'erreur utile. Essayez de l'ajouter à votre fichier de nœud. Il devrait afficher la trace complète de la pile où votre crash se produit.

process.on('unhandledRejection', (error, p) => {
  console.log('=== UNHANDLED REJECTION ===');
  console.dir(error.stack);
});
Joshuakcockrell
la source
La seule différence fonctionnelle est de faire un console.dir sur la propriété stack de l'erreur. Une grande différence de sortie par rapport à la réponse acceptée
joshuakcockrell le