如何在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参考:
done
与then
使用的黄金法则是:或者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.onPossiblyUnhandledRejection
。 done
的调用是不需要的,因为库会检查未处理的拒绝本身不像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); });
如果我在某个地方没有捕捉到,那么未被承认的诺言就会继续显示。 但是,如果我抓住它的地方…