【问题标题】:How to find which promises are unhandled in Node.js UnhandledPromiseRejectionWarning?如何在 Node.js UnhandledPromiseRejectionWarning 中找到未处理的承诺?
【发布时间】:2017-10-05 16:24:19
【问题描述】:

Node.js 版本 7 具有用于处理承诺的 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.

不幸的是,没有提到 catch 丢失的行。 有没有办法在不检查每个 try/catch 块的情况下找到它?

【问题讨论】:

  • 您可以使用 Bluebird Promise 库,它可能会为您提供堆栈跟踪。
  • 也许注册到 Node 的 unhandledRejection 事件会有所帮助?请参阅docs。您的回调获得了Error 对象和实际的Promise,我相信Error 对象可能包含堆栈跟踪。
  • 如果前面的两个 cmets 没有帮助,那么 Can't set headers after they are sent. 应该会给您一个线索,它可能会在您的代码中发生(即您在标头已经存在之后设置标头的地方)发送 - 大概是因为无法理解异步代码,但这是一个猜测)
  • 您好,消息有助于确定错误在代码中的位置,顺便说一句,这不像知道行那么容易。
  • @jfriend00 事实证明这是异步函数抛出错误的情况——那些异步函数的内部节点承诺永远不会使用 Bluebird,所以拥有 Bluebird 并没有帮助那个场景。

标签: node.js promise async-await warnings unhandled-exception


【解决方案1】:

收听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
});

【讨论】:

  • 记录 error.stack(或在上面的示例中为 reason.stack)为您提供错误的完整堆栈跟踪。
  • 我希望我可以说这有效,但它没有。我在节点 8.9.4 上。
  • 我尝试了上面的代码,但由于这两个原因都没有定义,p?有什么建议? " 未处理的拒绝:Promise { state: 'rejected', reason: undefined } reason: undefined "
  • 我将此代码添加到我的节点app.js 文件的顶部,但遗憾的是没有记录任何内容。节点v10.13.0.
  • 为什么这不是Node默认行为的一部分?我在 v14.8.0 上,即使我使用 --trace-warnings,它仍然显示完全无用的消息。
【解决方案2】:

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

节点 --trace-warnings app.js

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

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

该模块支持 Bluebird、ES6 Promises、Q、WhenJS、es6-promisethen/promise 以及符合任何未处理拒绝规范的任何内容(文档中的完整详细信息)。

【讨论】:

  • 使用节点 7.8.0,这给了我一堆内部节点模块的堆栈跟踪。 (节点:10372)UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝ID:2):在emitWarning(internal/process/promises.js:59:21)在emitPendingUnhandledRejections(internal/process/promises.js:86:11)处未定义._tickDomainCallback (internal/process/next_tick.js:136:7)
  • 我没有看到任何输出显示未处理的承诺问题在哪里。
  • 我将此添加到package.json 启动脚本中,但遗憾的是没有记录任何内容。节点v10.13.0.
  • @user1063287 确保标志在您的命令中的正确位置。我刚刚对答案添加了更新,以强调它需要脚本名称之前。
  • 您可能正在查看弃用警告的堆栈跟踪,而不是原始未处理错误(应该在弃用警告上方的某个位置)。
【解决方案3】:

使用堆栈跟踪记录

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

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

【讨论】:

  • 唯一的功能区别是在错误的堆栈属性上执行 console.dir。与接受的答案相比,输出存在很大差异。
  • 我试过了,但error.stack 对我来说是undefined。 :( 节点 v14.15.4
  • 这仅在 error 是 Error 的实例时才有效。如果 promise 被拒绝,它将不起作用。一个字符串值:throw "Some error"
【解决方案4】:

这个模块让我能够找到罪魁祸首: https://www.npmjs.com/package/trace-unhandled

  1. 安装

    npm i trace-unhandled
    
  2. 包含在代码中

    require('trace-unhandled/register');
    

【讨论】:

  • 漂亮,即插即用!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多