Como descobrir quais promessas não são tratadas no Node.js UnhandledPromiseRejectionWarning?

177

O Node.js da versão 7 possui açúcar sintático assíncrono / aguardado para lidar com promessas e agora no meu código o seguinte aviso aparece com bastante frequência:

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

Infelizmente, não há referência à linha em que a captura está ausente. Existe alguma maneira de encontrá-lo sem verificar cada bloco try / catch?

user1658162
fonte
Você poderia usar a biblioteca de promessas do Bluebird e provavelmente forneceria um rastreamento de pilha.
precisa saber é o seguinte
3
Talvez a inscrição no unhandledRejectionevento do Node ajude? Veja os documentos . Seu retorno de chamada obtém o Errorobjeto e o real Promise, e acredito que o Errorobjeto possa conter um rastreamento de pilha.
YSK
Se os dois comentários anteriores não ajudarem, Can't set headers after they are sent.você deve dar uma pista de onde isso pode estar acontecendo no seu código (ou seja, em algum lugar em que você esteja definindo cabeçalhos após o envio dos cabeçalhos - provavelmente por causa de uma falha na compreensão do código assíncrono , mas isso é um palpite)
Jaromanda X 7/17
oi, que as mensagens ajudam a encontrar onde está o código, mas não é tão fácil quanto conhecer a linha.
User1658162
1
@ jfriend00 Acontece que era uma situação em que uma função assíncrona estava apresentando um erro - as promessas internas do Node para funções assíncronas nunca usam Bluebird, portanto, ter o Bluebird não ajuda nesse cenário.
Adam Reis

Respostas:

297

ouvir unhandledRejectionevento do 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
});
cuixiping
fonte
35
O registro error.stack(ou no exemplo acima reason.stack) fornece o rastreamento completo da pilha do erro.
Adam Reis
Obrigado por colocar process.onem vez de server.on, como em tantos outros exemplos que eu encontrei
PhillipHolmes
9
Eu gostaria de poder dizer que funcionou, mas não funciona. Estou no nó 8.9.4.
Ffxsam
2
Eu tentei o código acima e fiquei indefinido por ambos os motivos ep? Alguma sugestão? "Rejeição não tratada em: Promessa {estado: 'rejeitado', motivo: indefinido} motivo: indefinido"
Jeremy
3
Adicionei esse código na parte superior do meu app.jsarquivo de nó e, infelizmente, nada é registrado. Node v10.13.0.
user1063287
71

A maneira correta de mostrar um rastreamento de pilha completo para rejeições não tratadas do ES6 Promise, é executar o Node.js com o --trace-warningssinalizador. Isso mostrará o rastreamento de pilha completo para cada aviso, sem a necessidade de interceptar a rejeição de dentro do seu próprio código. Por exemplo:

nó --trace-warnings app.js

Verifique se o trace-warningssinalizador vem antes do nome do seu .jsarquivo! Caso contrário, o sinalizador será interpretado como um argumento para o seu script e será ignorado pelo próprio Node.js.

Se você realmente deseja lidar com rejeições não tratadas (por exemplo, registrando-as), pode usar o meu unhandled-rejectionmódulo, que captura todas as rejeições não tratadas para todas as principais implementações do Promises que as suportam, com um único manipulador de eventos.

Esse módulo suportes Bluebird, promessas ES6, Q, WhenJS, es6-promise, then/promise, e tudo o que está em conformidade com qualquer uma das especificações de rejeição não tratadas (detalhes completos na documentação).

Sven Slootweg
fonte
20
Usar o nó 7.8.0 e tudo isso me fornece um rastreamento de pilha para vários módulos de nós internos. (nó: 10372) UnhandledPromiseRejectionWarning: rejeição de promessa não tratada (ID de rejeição: 2): indefinido em emitWarning (internal / process / promises.js: 59: 21) em emitPendingUnhandledRejections (internal / process / promises.js: 86: 11) no processo ._tickDomainCallback (internal / process / next_tick.js: 136: 7)
Will Lovett
3
Não vejo nenhum resultado que mostre onde está o problema da promessa não tratada.
Jason Leach
Adicionei isso para package.jsoniniciar o script e, infelizmente, nada foi registrado. Node v10.13.0.
user1063287
1
@ user1063287 Verifique se o sinalizador está no local correto em seu comando. Acabei de adicionar uma atualização à resposta, para enfatizar que ela precisa ir antes do nome do script.
Sven Slootweg 14/11
2
Você provavelmente está observando o rastreamento da pilha do aviso de reprovação, e não do erro não tratado original (que deve estar em algum lugar acima do aviso de reprovação).
Sven Slootweg
7

Registrando com Rastreio de Pilha

Se você estiver procurando por mais de uma mensagem de erro útil. Tente adicionar isso ao seu arquivo de nó. Ele deve exibir o rastreamento completo da pilha onde a falha está ocorrendo.

process.on('unhandledRejection', (error, p) => {
  console.log('=== UNHANDLED REJECTION ===');
  console.dir(error.stack);
});
joshuakcockrell
fonte
A única diferença funcional é fazer um console.dir na propriedade de pilha do erro. Uma diferença bastante grande na saída em comparação com a resposta aceita.
joshuakcockrell