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

我使用Cujo伟大的库当我的Node项目提供Promises / A +实现,虽然这个问题不是特定于节点的。

一般来说,什么时候是好的,它可以让我编写更易于维护的代码。

但是,当我的callback意外失败(访问一个nullvariables的属性等)时,这些exception被有效地吞噬了,这似乎是由Promises / A +规范指定的。 不幸的是,这意味着我没有得到任何关于错误的反馈 (除了在那一刻执行的callback停止)。 没有错误types或消息,没有行号。

为了显示:

// 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 }); 

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

  • 为每次调用提供失败callback(将原因/exception转储到控制台)
  • 将所有callback机构包装在试用版中
  • 乱丢“地标日志”的代码库ala console.log('I got here 123')

我只是做错了吗? 当然,我并不是唯一一个发现基于promise的代码差的可debugging性。 有没有一个明显的解决scheme,我错过了?

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


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

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

因此:

  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承诺的行为是没有指定的。 对于本地实现没有明确的要求。 不过,我知道厂商正在开发它,我希望引擎即使在本地实现中也能开始搞清楚。

下面是我如何检测Promise在Node上被拒绝但未捕获的情况:

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

除此之外,你可以使用这个猴子包装来为Node的ES6 Promise提供长的堆栈跟踪 。 它产生类似Q的longStackSupport输出。 由于性能方面的考虑,我不推荐在开发代码之外使用它。 (它在Node v4.4.1中为我工作,我还没有在Chrome或Firefox中testing过。)