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

时间:2014-01-08 08:58:01

标签: javascript node.js debugging promise

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

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

然而,当我的回调意外失败(访问空变量的属性等)时,异常被有效地吞噬了,如Promise / 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-catches中
  • 使用“landmark logs”ala console.log('I got here 123')
  • 乱丢代码库

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

2 个答案:

答案 0 :(得分:16)

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.

使用蓝鸟

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

答案 1 :(得分:9)

以下是我如何检测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中测试它。)