如何调试javascript承诺?

Yem*_*lat 70 javascript promise es6-promise

我试图了解如何调试基于promises的异步代码.By Promises我的意思是基于ECMAScript 6的承诺,通过调试我的意思是使用内置的chrome或firefox调试器.

我遇到的问题是 - 当发生错误时,无论我如何拒绝它,我都无法获得堆栈跟踪.

我试过这些:

console.log(new Error('Error occured'));
throw new Error('Throwing an Error');
return new Error('Error returned by the onRejected function');
reject(new Error('Pass Error to the reject function'));
Run Code Online (Sandbox Code Playgroud)

但是这些都不会返回代码中的实际错误或堆栈跟踪.

所以我的问题是 - 如何正确调试javascript Promises?

Ben*_*aum 59

这是一个很好讨论的话题,令人遗憾的是,这本身就很难实现.

调试Chrome中的原始ES6承诺非常糟糕.这是因为他们会默默地抑制错误,每当你省略一个catch时,它都不会给你任何迹象表明promise没有成功.更新:Chrome现在记录未处理的拒绝(请参阅此链接了解具体方法)

 Promise.resolve("foo").then(function(){
      throw new Error("You will never see this");// silent failure
 });
Run Code Online (Sandbox Code Playgroud)

在Firefox中,事情会好一些,因为它们执行未处理的拒绝检测 - 但是,它仍然很好,如果你在任何地方分配了承诺它将无法工作.

那么,可以做些什么呢?

包括Bluebird - 它是ES6承诺的超集,你可以在里面交换它​​,它有一个更丰富的API,它更快,它有惊人的堆栈跟踪.它是在考虑调试的基础上构建的,包括出色的错误处理功能.

一旦你包括Bluebird,请致电:

Promise.longStackTraces();
Run Code Online (Sandbox Code Playgroud)

这会慢一点(它仍然会非常快)并会给你惊人的错误信息.例如:

Promise.resolve().then(function outer() {
    return Promise.resolve().then(function inner() {
        return Promise.resolve().then(function evenMoreInner() {
            a.b.c.d()
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

在本机承诺中 - 这将是一个无声的失败并且将很难调试 - 使用Bluebird承诺,这将在您的控制台中显示一个大的红色错误,默认情况下为您提供:

ReferenceError: a is not defined
    at evenMoreInner (<anonymous>:6:13)
From previous event:
    at inner (<anonymous>:5:24)
From previous event:
    at outer (<anonymous>:4:20)
From previous event:
    at <anonymous>:3:9
    at Object.InjectedScript._evaluateOn (<anonymous>:581:39)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:540:52)
    at Object.InjectedScript.evaluate (<anonymous>:459:21)
Run Code Online (Sandbox Code Playgroud)

一旦你完成调试 - 你可以把它换掉然后回到原生的承诺.我个人认为我知道我在制作中有错误所以我不推荐它,但它肯定是可行的.

  • 好吧,它需要将堆栈跟踪拼接在一起,但仅限于错误 - 通常Bluebird非常快,并且在客户端具有长堆栈跟踪时性能仍然非常好. (2认同)

goa*_*oat 13

*这不能直接回答您的问题,但它可能会有所帮助.

Chrome devtools最近获得了一项新功能,可用于调试异步代码,例如Promises.

http://www.html5rocks.com/en/tutorials/developertools/async-call-stack/

基本上,在"源"选项卡中启用"异步"复选框,Chrome将为您重建调用堆栈,就像它是同步代码一样.

截图

  • 谷歌浏览器现在默认支持异步调用堆栈,并已删除该复选框:https://developers.google.com/web/updates/2017/05/devtools-release-notes#step-into-async (8认同)
  • @dandavis不,不会. (4认同)

Mat*_*s M 13

这个答案是对Benjamin Gruenbaum的回答的补充:如果你在promise链中使用catch语句,你将通过error.stack获得堆栈跟踪:

        Promise.longStackTraces();

        function outer() {
            return Promise.resolve();
        }

        function inner() {
            return Promise.resolve();
        }

        function evenMoreInner() {
            a.b.c.d()
        }

        Promise.resolve()
            .then(outer)
            .then(inner)
            .then(evenMoreInner())
            .catch(function (err) {
                    console.log(err.message);
                    console.log(err.stack);
                });
Run Code Online (Sandbox Code Playgroud)

错误信息:

ReferenceError: a is not defined
at evenMoreInner (test/test_promise.js:58:17)  <<<< HERE's the error!
at Context.<anonymous> (test/test_promise.js:64:23)
Run Code Online (Sandbox Code Playgroud)

  • 只是重申一点......我被`console.log(err)`不包含err.stack这一事实所迷惑.你需要`console.log(err.stack)`来查看详细信息. (3认同)
  • 谢谢你,错过了`stack`属性,并想知道它去了哪里,哈哈! (2认同)