如何在Promise中捕获未捕获的异常

时间:2015-01-17 16:39:47

标签: javascript exception promise

有没有办法全局捕获所有异常,包括Promise异常。例如:

    window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
        alert("Error occured: " + errorMsg);//or any message
        return false;
    }

    var myClass = function(){

    }


    var pr = new Promise(function(resolve, react){
        var myInstance = new myClass();
        myInstance.undefinedFunction(); // this will throw Exception
        resolve(myInstance);
    });


    pr.then(function(result){
        console.log(result);
    });

    // i know right will be this:
    // pr.then(function(result){
    //     console.log(result);
    // }).catch(function(e){
    //     console.log(e);
    // });

此脚本将无声地死亡而不会出错。萤火虫没什么。

我的问题是,如果我犯了一个错误并且忘了抓住它有没有办法在全球范围内捕捉它?

5 个答案:

答案 0 :(得分:22)

更新,原生承诺现在在大多数浏览器中执行以下操作:

window.addEventListener("unhandledrejection", function(promiseRejectionEvent) { 
    // handle error here, for example log   
});

我们前几天正在讨论这个问题。

以下是您如何使用bluebird:

window.onpossiblyunhandledexception = function(){
    window.onerror.apply(this, arguments); // call
}

window.onerror = function(err){
    console.log(err); // logs all errors
}

使用Bluebird,它也可以使用Promise.onPossiblyUnhandledRejection。不需要done的调用,因为库不会检测到未处理的拒绝本身(2016年更新 - 我现在为Q编写了代码并且执行此操作)。

对于本机承诺 - 他们最终向window.onerror或新处理程序报告,但规范过程尚未完成 - 您可以follow it here

答案 1 :(得分:15)

大多数承诺实施目前不提供您所指的功能类型,但许多第三方承诺库(包括Qbluebird)提供{{1将捕获并重新抛出任何未捕获的错误的方法,从而将它们输出到控制台。

编辑:请参阅Benjamin Gruenbaum关于Bluebird处理未捕获异常的功能的答案)

所以,如果你有这个,那么你只需遵循经验法则,你所使用的任何承诺应该被退回或终止done()

.done()

引用Q API参考:

  

pr.then(function(result){ console.log(result); }) .done(); done用法的黄金法则是:then您对其他人的承诺,或者如果链条与您结束,请致电{{1}终止它。使用return终止是不够的,因为done处理程序本身可能会抛出错误。

我意识到这仍然需要一些额外的工作,你仍然可以忘记这样做,但它比必须catch并明确处理每个错误是一个改进,特别是出于上面指出的原因。

答案 2 :(得分:4)

在Node.js中,您可以使用:

process.on('unhandledRejection', (reason, promise) => {
  console.error(`Uncaught error in`, promise);
});

答案 3 :(得分:2)

如果你正在编写可以在浏览器中执行的代码。在Node.js环境中,您可以将代码包装在一个自执行的函数中,如下所示:

var isNode = (typeof process !== 'undefined' && typeof process.on !== 'undefined');
(function(on, unhandledRejection) {
    // PUT ANY CODE HERE
    on(unhandledRejection, function(error, promise) {
        console.error(`Uncaught error in`, promise);
    });
    // PUT ANY CODE HERE
})(
    isNode ? process.on.bind(process) : window.addEventListener.bind(window),
    isNode ? "unhandledRejection" : "unhandledrejection"
);

如果您使用此代码会发生什么:

  • 如果您在Node.js环境中运行它,您的处理程序将附加到进程对象,并在承诺中有未捕获的异常时执行。

  • 如果您在浏览器环境中运行它,您的处理程序将附加到窗口对象,并在承诺中有未捕获的异常并且您的浏览器支持unhandledrejection事件时执行。

  • 如果您在不支持unhandledrejection的浏览器环境中运行它,您将无法捕获未捕获的异常,并且永远不会触发unhandledrejection事件处理程序,但如果没有未被捕获的例外情况,你不会得到任何错误。

答案 4 :(得分:1)

如果您使用的是本机Promise,那很简单 你只需要.catch拒绝某些地方。

ajax(request).catch(function(rejected){
      console.log(rejected);
});

如果我不能在某个地方抓住它,那未被承诺的未来将继续呈现。 但是,如果我在某处抓到它......