为什么 try catch 块不捕获 promise 异常?

Why doesn't the try catch block catch the promise exception?

我对使用 promises 进行错误处理感到困惑。答案可能很明显,但我不明白。

我有以下示例代码:

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 块不应该处理错误吗?

我可以看出您的问题有两个可能的方面:

  1. test 中抛出的错误在 test 的同步(非异步)部分。为什么是 promise 拒绝而不是同步异常?

  2. 来自 test() 的承诺被拒绝了,为什么 catch 没有捕捉到拒绝?

#1 - 为什么拒绝?

因为即使 async 函数在其工作的同步部分抛出异常,这也只是拒绝了它 returns 的承诺,它 不会 引发同步错误。这只是 async 函数设计过程中做出的一个设计决定,而且是一个聪明的决定——如果在函数的同步部分抛出时是一个同步错误,但之后又是一个 promise 拒绝,那将是混乱和困难的了解。所以很简单:投入一个 async 函数总是拒绝它的承诺。

(这与 promise 构造函数如何处理您传递给它的执行器回调是一致的。当您执行 new Promise((resolve, reject) => /*...*/}) 时,promise 构造函数会同步调用您的函数,但如果您在调用期间抛出,它会使用你抛出什么来拒绝承诺而不是允许它作为同步异常继续。)

#2 - 为什么 catch 块没有捕捉到拒绝?

因为您没有使用 await。当您 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...
}