【问题标题】:How do I debug promise-based code in node?如何在节点中调试基于承诺的代码?
【发布时间】:2014-01-26 06:37:58
【问题描述】:

我正在使用 Cujo 出色的 When 库为我的 Node 项目提供 Promises/A+ 实现,尽管这个问题不是特定于节点的。

一般来说,什么时候很棒:它让我可以编写更易维护、更易读的代码。

但是,当我的回调意外失败(访问空变量的属性等)时,异常会被When 有效地吞没,就像 Promises/A+ 规范中的specified 一样。不幸的是,这意味着我没有得到任何关于错误的反馈(除了回调在那个时候停止执行)。没有错误类型或消息,没有行号。

举例说明:

// hypothetical asynchronous database query
database.query(queryDetails).then(function(result) {

  var silly = 3.141592654;
  silly(); // TypeError: number is not a function!

  process(result); // this code is silently never executed

});

我能想到一些(不可接受的)方法来解决这个问题:

  • 为每个then 调用提供失败回调(将原因/异常转储到控制台)
  • 将所有回调主体包装在 try-catch 中
  • 在代码库中乱扔“标志性日志”ala console.log('I got here 123')

我只是做错了吗?当然,并不是只有我一个人发现基于 Promise 的代码的可调试性很差。我是否缺少明显的解决方案?

【问题讨论】:

  • 首选 Bluebird 而不是何时。它有 AMAZING 堆栈跟踪(好多了)。哦,不用担心性能,它也快得多。此外,bluebird 将未处理的异常记录到 stderr(通常是控制台),并带有完整的堆栈跟踪。它还可以通过 catch 等进行非常好的错误处理。
  • 谢谢本杰明 - 这是一个答案吗?
  • 不,这是我自己处理问题后的图书馆建议。图书馆建议是不好的答案:) 我不确定“When”是否有一个好的 unhandledExceptionHandler。老实说,与 Bluebird 相比,Node 中所有其他的 Promise 库都显得非常幼稚。
  • unhandledExceptionHandler!!现在只是阅读它,它有一个“监视器”。太奇怪了,这个问题没有被 Promises/A+ 规范处理......
  • Promises/A+ 规范并不是要进行实际的 Promise 实现(它甚至没有指定创建 Promise 的方法),而是对良好互操作的最低要求。

标签: javascript node.js debugging promise


【解决方案1】:

2016 年 9 月更新:NodeJS 6.6.0+ 和 7.0+ 将在未处理的拒绝时自动发出警告。使用--trace-warnings 运行节点以获得合理的堆栈跟踪。仍然不如蓝鸟给你的那么好,但比以前的情况好很多。


好的,那么总结一下来自cmets的信息并补充一些。

  • Promises/A+ 规范中没有任何内容规定如何处理此问题。该规范是关于不同 Promise 库之间良好互操作的最低要求 - 因此一个 Promise 库可以使用在另一个 Promise 中创建的 Promise,反之亦然。
  • 几个库通过包含明确声明链已结束的.done 方法来解决此问题,这会导致抛出未捕获的拒绝。像When和Q这样的库就是这样解决问题的。例如,如果您在 .query 之后的 .then.done,您会得到一个很长的堆栈跟踪。
  • 像 Bluebird 这样较新的、不那么幼稚的 Promise 实现通过自动找出可能未被捕获的拒绝并大声为您注销来解决此问题。他们还给你一个钩子。何时使用监视器对此提供实验性支持。

这样:

 require('when/monitor/console'); // when will now log async rejections used with
                                  // `then` , this is experimental in when.

蓝鸟

Promise.longStackTraces(); // Bluebird always logs async rejections but with this 
                           // option it will stitch the asynchronous context stack
                           // for you in your methods.
  • ES6 承诺的行为在此未指定。对此,本机实现没有明确的要求。不过,我知道供应商正在努力解决这个问题,我希望引擎即使在本机实现中也能开始解决这个问题。

【讨论】:

  • 为什么这不是默认开启的?!此外,即使我启用了这个,我也没有得到行号或错误堆栈跟踪。我应该如何找到它发生在哪里?
  • @Tomas 默认情况下它是打开的,-您可以登录到一个文件,所有这些功能都需要数百小时-我们真的可以在改进工具方面使用一些帮助。为错误的默认值道歉,当我开始处理它时,事件不存在并且异常被吞下,之后我们添加了事件 - 然后在 6.6 中默认跟踪。 V8 增加了 util.promisify、async_hooks 支持和更好的跟踪——我们正在努力改进,但这只是我们大多数人的爱好。不过,对于糟糕的调试体验感到抱歉!
  • 感谢您的回答。但实际上,我需要做的就是捕获异常并打印堆栈跟踪。警告未处理异常的代码清楚地捕获了它,所以它也可以在您捕获它的同时打印堆栈跟踪?无论如何,感谢您如此专注于此。我当然感谢 Node.js 和其中的一切,它是我做很多事情时最喜欢的平台!
【解决方案2】:

以下是我如何检测一个 Promise 在 Node 上被拒绝但未被捕获的时间:

if (typeof process === 'object') {
    process.on('unhandledRejection', (error, promise) => {
        console.error("== Node detected an unhandled rejection! ==");
        console.error(error.stack);
    });
}

除此之外,您还可以使用monkey wrapper to provide long stack traces for Node's ES6 Promises。它产生与 Q 的longStackSupport 类似的输出。由于性能问题,我不建议在开发代码之外使用它。 (它在 Node v4.4.1 中对我有用。我还没有在 Chrome 或 Firefox 中测试过。)

【讨论】:

  • 这个答案帮助我检测到承诺中未定义的函数。
猜你喜欢
  • 2016-01-08
  • 1970-01-01
  • 2021-01-27
  • 2018-05-11
  • 2014-11-07
  • 1970-01-01
  • 2016-02-02
  • 1970-01-01
相关资源
最近更新 更多