如何在节点中调试基于承诺的代码?

aaa*_*dan 8 javascript debugging node.js promise

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

通常,什么时候很棒:它让我编写更易于维护,可读的代码.

但是,当我的回调意外失败(访问null变量的属性等)时,异常会被When有效吞并,似乎由Promises/A +规范指定.不幸的是,这意味着我没有得到任何关于错误的反馈(除了回调在此时停止执行).没有错误类型或消息,没有行号.

为了显示:

// 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

});
Run Code Online (Sandbox Code Playgroud)

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

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

我只是做错了吗?当然,我并不是唯一一个发现基于promises的代码可调试性差的人.有一个明显的解决方案我错过了吗?

Ben*_*aum 17

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


好的,所以总结评论中的信息并添加一些.

  • Promises/A +规范中没有任何内容规定如何处理这个问题.规范是关于不同promise库之间良好互操作的最低要求 - 因此一个promise库可以消耗在另一个promise中创建的promise,反之亦然.
  • 有几个库通过包含一个.done明确声明链已经结束的方法来解决这个问题,这会导致抛出未被捕获的拒绝.像When和Q这样的库以这种方式解决问题.例如,如果你的.then后来.query是一个.done你得到一个很长的堆栈跟踪.
  • 较新的,不太天真的承诺实施,如Bluebird通过自动找出可能未被捕获的拒绝并大声记录它来解决这个问题.他们还会给你一个钩子.何时使用显示器对此进行实验支持.

因此:

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

用蓝鸟

Promise.longStackTraces(); // Bluebird always logs async rejections but with this 
                           // option it will stitch the asynchronous context stack
                           // for you in your methods.
Run Code Online (Sandbox Code Playgroud)
  • ES6承诺的行为没有具体说明.对于本机实现没有明确的要求.但是,我知道供应商正在研究它,我希望引擎即使在本机实现中也能开始解决这个问题.

  • 更新 - 我们正在努力:) https://github.com/iojs/io.js/issues/256 (3认同)

joe*_*dle 9

以下是我如何检测Promise在Node上被拒绝但未被捕获的方式:

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

除此之外,您可以使用此Monkey包装器为Node的ES6 Promises提供长堆栈跟踪.它产生与Q类似的输出longStackSupport.由于性能问题,我不建议在开发代码之外使用它.(它在Node v4.4.1中为我工作.我还没有在Chrome或Firefox中测试它.)