如何调试javascript承诺?

时间:2014-09-13 20:11:17

标签: 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'));

但是这些都没有返回代码中的实际错误或堆栈跟踪。

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

6 个答案:

答案 0 :(得分:58)

这是一个很好讨论的话题,令人遗憾的是,这实际上很难与原生承诺相提并论。

调试Chrome中的原始ES6承诺非常糟糕。这是因为他们会默默地抑制错误,每当你忽略一个捕获时,它都不会给你任何迹象表明承诺失败。更新:Chrome现在记录未处理的拒绝(see this link for how)

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

在Firefox中,由于它们执行未处理的拒绝检测,事情会好一些 - 但是,它仍然很有趣,如果您在任何地方分配了承诺,它将无效。

那么,可以做些什么呢?

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

一旦你加入Bluebird,请致电:

Promise.longStackTraces();

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

Promise.resolve().then(function outer() {
    return Promise.resolve().then(function inner() {
        return Promise.resolve().then(function evenMoreInner() {
            a.b.c.d()
        });
    });
});

在本机承诺中 - 这将是一个无声的失败,并且将很难调试 - 使用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)

完成调试后 - 您可以将其换出并回到本机承诺。我个人认为我知道自己在制作中有错误所以我不推荐它,但它肯定是可行的。

答案 1 :(得分:13)

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

Chrome devtools最近推出了一项新功能,可用于调试异步代码,例如Promises。

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

基本上,在“来源”标签中启用“异步”复选框,Chrome会为您重建调用堆栈,就好像它是同步代码一样。

Screenshot

答案 2 :(得分:12)

这个答案是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);
                });

错误讯息:

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)

答案 3 :(得分:1)

他们似乎正在使用Chrome中的调试工具。有关详细信息,请参阅此主题。

https://code.google.com/p/v8/issues/detail?id=3093

我已经检查过它是否已经在开发版或测试版中,但我希望它很快就会出现。它可能会在2015年1月左右包含在正常版本中(只是个人猜测,绝对没有承诺,因为我甚至不能为Google工作)。

答案 4 :(得分:0)

调试承诺的最佳方法是收听unhandledRejection的{​​{1}}事件。

例如,以下是如何设置它并转储堆栈跟踪...

process

答案 5 :(得分:0)

您可以在Promise对象的.then()函数中添加console.log()语句: 如果需要,您还可以添加.catch()。

genericDbCaller(dbName, collectionName, dbFunctionName, params) {
        return new Promise((resolve, reject) => {
            DatabaseContext.instance.getDbConn(dbName)
                .then((dbConn) => {
                    dbConn.get(collectionName)[dbFunctionName].apply(null, params)
                        .then(

                            (docs) =>{
                    ----->>>        console.log(docs);  
                            resolve(docs);
                        })
                        .catch((e)=>{