为什么Try Catch块没有捕获Promise异常?
我对承诺的错误处理感到困惑。答案可能很明显,但我不明白。
我有以下示例代码:
var test = async function(){
throw new Error('Just another error')
}
try {
test().then()
}
catch(err){
alert('error: ' + err.toString())
}
在我的浏览器中,我没有收到警告,并且Uncaught (in promise) Error
在控制台中。为什么会这样呢?是否应该使用Try..Catch块处理该错误?
解决方案
我可以看到您问题的两个可能方面:
test
中抛出的错误位于test
的同步(非异步)部分。为什么它是承诺拒绝而不是同步例外?来自
test()
的承诺正在被拒绝,为什么catch
没有捕获该拒绝?
#1-为什么是拒绝?
因为即使async
函数在其工作的同步部分抛出,这只是拒绝它返回的承诺,不会引发同步错误。这只是在设计async
函数时做出的一个设计决定,而且是一个聪明的决定--如果在抛出函数的同步部分时是同步错误,但在那之后是承诺被拒绝,那将是混乱和难以理解的。所以很简单:抛出一个async
函数总是拒绝它的承诺。
(这与Promise构造函数处理传入的Executor回调的方式一致。当您这样做时new Promise((resolve, reject) => /*...*/})
,Promise构造函数同步调用您的函数,但如果您在调用过程中引发,它将使用您抛出的内容来拒绝Promise,而不是允许它作为同步异常继续。)
#2-catch
块为什么没有捕获拒绝?
因为您没有使用await
。只有当您正在履行承诺时,拒绝承诺才是例外。如果使用Promise方法then
/catch
/finally
附加处理程序,则通过调用拒绝处理程序而不是异常机制来处理拒绝。
因此要么使用Promise方法附加履行处理程序,要么使用拒绝处理程序:
test()
.then(result => {
// ...use `result` here...
})
.catch(error => {
// ...handle/report error here...
});
或在async
函数中使用await
(如果您的环境中有顶级await
,则在模块的顶层使用):
// In an `async` function (or the top level of a module in cutting-edge environments)
try {
const result = await test();
// ...use `result` here...
}
catch(err){
// ...handle/report error here...
}
相关文章