简体   繁体   English

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

[英]How do I debug promise-based code in node?

I am using Cujo's great When library to provide a Promises/A+ implementation for my Node project, although this question is not node-specific. 我正在使用Cujo的伟大When库为我的Node项目提供Promises / A +实现,尽管这个问题不是特定于节点的。

Generally, When's great: it lets me write more maintainable, readable code. 通常,什么时候很棒:它让我编写更易于维护,可读的代码。

However, when my callbacks fail unexpectedly (accessing a property of a null variable, etc), the exceptions are effectively swallowed by When, as seems to be specified by the Promises/A+ spec. 但是,当我的回调意外失败(访问null变量的属性等)时,异常会被When有效地吞噬,似乎由Promises / A +规范指定 Unfortunately, this means I don't get any feedback about the error (other than the callback stops executing at that point). 不幸的是,这意味着我没有得到任何关于错误的反馈 (除了回调在此时停止执行)。 No error type or message, no line number. 没有错误类型或消息,没有行号。

To illustrate: 为了显示:

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

});

I can think of a handful of (unacceptable) ways to tackle this: 我可以想到一些(不可接受的)方法来解决这个问题:

  • providing failure callbacks for every then call (to dump the reason/exception to the console) 每一个提供失败的回调then调用(抛售的理由/例外控制台)
  • wrapping all callback bodies in try-catches 将所有回调主体包装在try-catches中
  • littering the codebase with "landmark logs" ala console.log('I got here 123') 使用“地标日志”ala console.log('I got here 123')乱丢代码库

Am I just doing it wrong? 我只是做错了吗? Surely I'm not alone in finding the debuggability of promises-based code poor. 当然,我并不是唯一一个发现基于promises的代码可调试性差的人。 Is there an obvious solution I'm missing? 有一个明显的解决方案我错过了吗?

Update Sep 2016: NodeJS 6.6.0+ and 7.0+ will warn automatically on unhandled rejections. 2016年9月更新: NodeJS 6.6.0+和7.0+将在未处理的拒绝时自动发出警告。 Run node with --trace-warnings to get reasonable stack traces. 使用--trace-warnings运行节点以获得合理的堆栈跟踪。 Still not as good as what bluebird gives you but a lot better than the situation before. 仍然不如蓝鸟给你的好,但比以前的情况要好很多。


Ok, so summing up the information from the comments and add some. 好的,所以总结评论中的信息并添加一些。

  • There is nothing in the Promises/A+ specification that dictates how to deal with this problem. Promises / A +规范中没有任何内容规定如何处理这个问题。 The specification is about the minimal requirements for good interop between different promise libraries - so one promise library can consume promises created in another and vice versa. 规范是关于不同promise库之间良好互操作的最低要求 - 因此一个promise库可以消耗在另一个promise中创建的promise,反之亦然。
  • Several libraries solve this problem by including a .done method that explicitly declares the chain has ended, this causes uncaught rejections to be thrown. 有几个库通过包含一个明确声明链已经结束的.done方法来解决这个问题,这会导致抛出未被捕获的拒绝。 Libraries like When and Q solve the problem this way. 像When和Q这样的库以这种方式解决问题。 For example if your .then after .query was a .done you'd get a long stack trace. 例如,如果你的.then之后的.query是一个.done你会得到一个很长的堆栈跟踪。
  • Newer, less naive implementations of promises like Bluebird solve this problem by automatically figuring out possibly uncaught rejections and logging them out for you loudly. 较新的,不太天真的承诺实施,如Bluebird通过自动找出可能未被捕获的拒绝并大声记录它来解决这个问题。 They also give you a hook. 他们还会给你一个钩子。 When has experimental support for this using the monitor. 何时使用显示器对此进行实验支持。

As such: 因此:

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

With bluebird 用蓝鸟

Promise.longStackTraces(); // Bluebird always logs async rejections but with this 
                           // option it will stitch the asynchronous context stack
                           // for you in your methods.
  • ES6 promises' behavior is unspecified on this. ES6承诺的行为没有具体说明。 There is no explicit requirements on the native implementations with regards to this. 对于本机实现没有明确的要求。 However, I know vendors are working on it and I'd expect engines to start figuring this out even in native implementations. 但是,我知道供应商正在研究它,我希望引擎即使在本机实现中也能开始解决这个问题。

Here is how I detect when a Promise has been rejected on Node but not caught: 以下是我如何检测Promise在Node上被拒绝但未被捕获的方式:

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

In addition to that, you could use this monkey wrapper to provide long stack traces for Node's ES6 Promises . 除此之外,您可以使用此Monkey包装器为Node的ES6 Promises提供长堆栈跟踪 It produces similar output to Q's longStackSupport . 它产生类似于Q的longStackSupport输出。 I would not recommend it for use outside of development code, due to performance concerns. 由于性能问题,我不建议在开发代码之外使用它。 (It's working for me in Node v4.4.1. I have not yet tested it in Chrome or Firefox.) (它在Node v4.4.1中为我工作。我还没有在Chrome或Firefox中测试它。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM