首页 文章

如何调试javascript承诺?

提问于
浏览
62

我试图了解如何调试基于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 回答

  • 56

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

    调试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 - 它's a superset of ES6 promises and you can swap it right inside, it has a richer API, it'更快,它有惊人的堆栈跟踪 . 它是在考虑调试的基础上构建的,包括出色的错误处理功能 .

    一旦你包括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)
    

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

  • 10

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

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

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

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

    Screenshot

  • 1

    调试承诺的最佳方法是收听 processunhandledRejection 事件 .

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

    process.on('unhandledRejection', (reason, p) => {
       console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
       // Stack Trace
       console.log(reason.stack);
     });
    
  • 13

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

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

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

  • 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)=>{
    
  • 0

    这个答案是Benjamin Gruenbaum的补充's answer: If you use a catch statement in the promise chain, you' ll得到 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)
    

相关问题