如何在Promise中捕捉未捕获的exception

有没有办法在全球范围内捕捉所有exception,包括Promiseexception。 例:

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); // }); 

这个脚本将会无声无息地死掉。 没有在萤火虫。

我的问题是,如果我犯了一个错误,忘了抓它,有没有什么办法可以在全球范围内捕捉到它?

大多数承诺实现目前不提供您所指的functiontypes,但是许多第三方承诺库(包括Q和bluebird )提供了一个done()方法,可以捕获并重新抛出任何未被捕获的错误,从而输出它们到控制台。

编辑:请参阅本杰明Gruenbaum关于蓝鸟的function处理未捕获的exception的答案)

所以,如果你有这个,你只需要按照经验法则,你使用的任何承诺应该返回或用.done()终止:

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

引用Q API参考:

donethen使用的黄金法则是:或者return你的承诺return给其他人,或者如果链条以你为终点,则调用done来终止它。 catch来终止是不够的,因为catch处理器本身可能会抛出一个错误。

我意识到,这仍然需要一些额外的工作,你仍然可以忘记这样做,但是这是一个改进,因为必须.catch()和显式处理每个错误,特别是上面指出的原因。

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

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

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

以下是你如何使用蓝鸟做到这一点:

 window.onpossiblyunhandledexception = function(){ window.onerror.apply(this, arguments); // call } window.onerror = function(err){ console.log(err); // logs all errors } 

使用蓝鸟也可以使用Promise.onPossiblyUnhandledRejectiondone的调用是不需要的,因为库会检查未处理的拒绝本身不像Q(UPDATE 2016 – 我现在写Q代码,它是这样的)。

至于原生的承诺 – 他们最终报告给window.onerror或新的处理程序,但规范过程尚未完成 – 你可以在这里按照它 。

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

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

如果您正在编写可以在浏览器和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环境中运行它,你的处理程序将被附加到进程对象,并在promise中有一个未捕获的exception时被执行。

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

  • 如果您在浏览器环境中运行它,而不支持unhandledrejection ,则将无法捕获未捕获的exception,并且unhandledrejection事件处理程序将永远不会被触发,但是如果没有未捕获的exception,则不会出现任何错误。

如果你使用原生Promise,那很简单。
你只需.catch这个拒绝一些地方。

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

如果我在某个地方没有捕捉到,那么未被承认的诺言就会继续显示。 但是,如果我抓住它的地方…