Come trovare quali promesse non vengono gestite in Node.js UnhandledPromiseRejectionWarning?


177

Node.js dalla versione 7 ha asincrono / attendono lo zucchero sintattico per gestire le promesse e ora nel mio codice appare abbastanza spesso il seguente avviso:

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

Sfortunatamente non c'è alcun riferimento alla linea in cui manca il fermo. C'è un modo per trovarlo senza controllare ogni blocco try / catch?


Potresti usare la libreria di promesse Bluebird e probabilmente ti darebbe una traccia dello stack.
jfriend00,

3
Forse la registrazione unhandledRejectionall'evento di Node sarà di aiuto? Vedi i documenti . Il callback ottiene l' Erroroggetto e l'effettivo Promise, e credo che l' Erroroggetto possa contenere una traccia dello stack.
YSK

Se i due commenti precedenti non sono di aiuto, allora Can't set headers after they are sent.dovresti darti un indizio su dove potrebbe accadere nel tuo codice (ad es. Da qualche parte stai impostando le intestazioni dopo che le intestazioni sarebbero già state inviate - presumibilmente a causa di un errore nella comprensione del codice asincrono , ma è un'ipotesi)
Jaromanda X

ciao che i messaggi aiutano sicuramente a trovare dove si trova il codice nel bug, tra l'altro non è facile come conoscere la linea.
user1658162

1
@ jfriend00 Si è scoperto che era una situazione in cui una funzione asincrona generava un errore: quelle promesse interne del nodo per le funzioni asincrone non usano mai Bluebird, quindi avere Bluebird non aiuta in quello scenario.
Adam Reis,

Risposte:


298

ascolta l' unhandledRejectionevento del processo.

process.on('unhandledRejection', (reason, p) => {
  console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
  // application specific logging, throwing an error, or other logic here
});

35
La registrazione error.stack(o nell'esempio precedente reason.stack) fornisce la traccia dello stack completa dell'errore.
Adam Reis,

9
Vorrei poter dire che ha funzionato, ma non lo è. Sono sul nodo 8.9.4.
ffxsam,

2
Ho provato il codice sopra e non sono stato definito per entrambi i motivi, e p? Eventuali suggerimenti? "Rifiuto non gestito a: Promessa {stato: 'rifiutato', motivo: non definito} motivo: non definito"
Jeremy

1
Ho provato questo e ha funzionato come un fascino! Risolto il mio problema molto rapidamente.
smb,

3
Ho aggiunto questo codice all'inizio del mio app.jsfile del nodo e purtroppo non è stato registrato nulla. Nodo v10.13.0.
user1063287

71

Il modo corretto di mostrare una stack stack completa per i rifiuti di Promessa ES6 non gestiti è eseguire Node.js con il --trace-warningsflag. Questo mostrerà l'intero stacktrace per ogni avviso, senza dover intercettare il rifiuto all'interno del tuo codice. Per esempio:

nodo --trace-warnings app.js

Assicurati che la trace-warningsbandiera venga prima del nome del tuo .jsfile! In caso contrario, il flag verrà interpretato come argomento per lo script e verrà ignorato dallo stesso Node.js.

Se si desidera gestire effettivamente i rifiuti non gestiti (ad es. Registrandoli), è possibile utilizzare unhandled-rejectioninvece il mio modulo, che rileva tutti i rifiuti non gestiti per tutte le principali implementazioni di Promises che lo supportano, con un singolo gestore eventi.

Che supporta moduli Bluebird, Promises ES6, Q, WhenJS, es6-promise, then/promise, e tutto ciò che è conforme a una qualsiasi delle specifiche di rigetto non gestite (dettagli completi nella documentazione).


20
L'uso del nodo 7.8.0 e tutto ciò mi dà una traccia dello stack per un mucchio di moduli di nodi interni. (nodo: 10372) UnhandledPromiseRejectionWarning: rifiuto della promessa non gestito (ID rifiuto: 2): non definito in emitWarning (internal / process / promises.js: 59: 21) in emitPendingUnhandledRejections (internal / process / promises.js: 86: 11) al processo ._tickDomainCallback (internal / process / next_tick.js: 136: 7)
Will Lovett

3
Non vedo alcun output che mostri dove si trova il problema di promessa non gestita.
Jason Leach,

Ho aggiunto questo per package.jsonavviare lo script e purtroppo non è stato registrato nulla. Nodo v10.13.0.
user1063287

1
@ user1063287 Assicurarsi che il flag sia nella posizione corretta nel comando. Ho appena aggiunto un aggiornamento alla risposta, per sottolineare che deve andare prima del nome dello script.
Sven Slootweg,

2
Probabilmente stai guardando la traccia dello stack dell'avviso di deprecazione, non dell'errore non gestito originale (che dovrebbe trovarsi da qualche parte sopra l'avvertimento di deprecazione).
Sven Slootweg,

7

Registrazione con traccia stack

Se stai cercando un messaggio di errore più utile. Prova ad aggiungere questo al tuo file del nodo. Dovrebbe visualizzare la traccia dello stack completo in cui si sta verificando il crash.

process.on('unhandledRejection', (error, p) => {
  console.log('=== UNHANDLED REJECTION ===');
  console.dir(error.stack);
});

L'unica differenza funzionale sta facendo un console.dir sulla proprietà dello stack dell'errore. Abbastanza una differenza nell'output rispetto alla risposta accettata.
joshuakcockrell,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.