如何在Node.js UnhandledPromiseRejectionWarning中查找未处理的承诺?


176

版本7中的Node.js具有用于处理promise的async / await语法糖,现在在我的代码中经常出现以下警告:

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

不幸的是,没有提到丢失渔获物的那一行。有没有找到所有方法而不检查每个try / catch块的方法?


您可以使用Bluebird Promise库,它很可能会为您提供堆栈跟踪。
jfriend00

3
也许注册Node的unhandledRejection事件会有所帮助?请参阅文档。您的回调会获取Error对象和实际对象Promise,我相信Error对象可能包含堆栈跟踪。
YSK

如果前两个注释没有帮助,那么Can't set headers after they are sent.应该给您一个提示,它可能在代码中发生什么地方(即,在已经发送了标头之后,您正在设置标头的某个地方-大概是因为未能理解异步代码) ,但这是一个猜测)
Jaromanda X

嗨,这些消息可以肯定地帮助您找到错误在代码中的位置,但要知道那行并不容易。
user1658162

1
@ jfriend00事实证明,在这种情况下,异步函数引发了错误-这些内部节点对异步函数的承诺永远不会使用Bluebird,因此拥有Bluebird在这种情况下无济于事。
亚当·里斯

Answers:


297

监听unhandledRejection进程事件。

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
日志记录error.stack(或在上面的示例中reason.stack)为您提供了错误的完整堆栈跟踪。
亚当·里斯

感谢您提供process.on而不是server.on喜欢我发现的许多其他示例
PhillipHolmes,

9
我希望我可以说这行得通,但事实并非如此。我在节点8.9.4上。
ffxsam

2
我尝试了上面的代码,但由于两个原因都未定义,所以p?有什么建议?“未处理的拒绝于:承诺{状态:'被拒绝',原因:未定义}原因:未定义“
Jeremy

3
我将此代码添加到我的节点app.js文件的顶部,但不幸的是没有任何记录。节点v10.13.0
user1063287

71

显示未处理的ES6 Promise拒绝的完整堆栈跟踪的正确方法是运行带有--trace-warnings标志的Node.js。这将显示每个警告的完整堆栈跟踪,而不必从您自己的代码中截取拒绝。例如:

节点--trace-warnings app.js

确保trace-warnings标志位于文件名之前.js!否则,该标志将被解释为脚本的参数,Node.js本身将忽略该标志。

如果要实际处理未处理的拒绝(例如,通过记录它们),则可能要改用我的unhandled-rejection模块,该模块使用单个事件处理程序捕获支持它的每个主要Promises实现的所有未处理的拒绝。

该模块支持蓝鸟,ES6承诺,Q,WhenJS, ,es6-promisethen/promise和任何符合任何未处理的抑制规范(文档中的全部细节)的。


20
使用节点7.8.0,这给了我很多内部节点模块的堆栈跟踪信息。(节点:10372)UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝ID:2):在processWatingPendingUnhandledRejections(internal / process / promises.js:86:11)时在embedWarning(internal / process / promises.js:59:21)时未定义._tickDomainCallback(internal / process / next_tick.js:136:7)
Will Lovett

3
我没有看到任何输出显示未处理的承诺问题在哪里。
杰森·里奇

我将其添加到package.json启动脚本中,但不幸的是没有记录任何内容。节点v10.13.0
user1063287

1
@ user1063287确保标志在命令中的正确位置。我刚刚在答案中添加了一个更新,以强调它需要放在脚本名称之前
Sven Slootweg

2
您可能正在查看的是过时警告的堆栈跟踪,而不是原始未处理错误的堆栈跟踪(错误应该在过时警告之上)。
Sven Slootweg

6

使用堆栈跟踪记录

如果您正在寻找更多有用的错误消息。尝试将其添加到您的节点文件中。它应该显示发生崩溃的完整堆栈跟踪。

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

唯一的功能差异是在错误的堆栈属性上执行console.dir。与接受的答案相比,输出的差异很大。
joshuakcockrell
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.