提问者:小点点

在JavaScript中捕获异步函数中的所有promise拒绝


在异步函数(JavaScript-NodeV8.4.0)中等待多个承诺后抛出拒绝错误时,我遇到了一个捕获所有错误的问题。

请参考以下JavaScript:

作为参考,函数timeoutOne()和timeoutTwo()仅返回一个本机承诺,分别在1秒和2秒超时后解析一个值,或者如果我将“deviousState”设置为true,则返回一个错误。

let deviousState = true;

async function asyncParallel() {
  try {
    let res1 = timeoutOne();
    let res2 = timeoutTwo();
    console.log(`All done with ${await res1} ${await res2}`)
  }
  catch(err) {
    console.log(err)
  }
}
asyncParallel();

let pAll = Promise.all([timeoutOne(), timeoutTwo()]);
pAll.then((val) => {
  console.log(`All done with ${val[0]} ${val[1]}`)
}).catch(console.log);

在这两种情况下,只有首先返回的promise记录错误。我知道在一些promise库中有一种记录所有错误的方法(例如bluebird中的“settle”方法,但是,我不确定在原生Promises中是否有类似于此方法的方法?

另外,如果两个承诺都拒绝,那么asyncParallel()将记录一个未捕获的错误,其中的承诺最后拒绝。那是因为异步函数的try/catch块没有内置机制以这种方式捕获多个拒绝吗?

如果承诺得到解决,在这两种情况下,一切都是一样的。只是当两者都拒绝时,promise.all处理错误,并且异步函数版本声明未处理的promise错误之一将使Node的未来版本中的进程崩溃。

不管怎么说,try/catch是否可以正确处理这种类型的错误?或者我仍然需要在异步函数内部使用一个允诺,以确保错误得到正确处理吗?


共1个答案

匿名用户

如果两个承诺都拒绝,那么将记录一个未捕获的错误,该错误带有最后拒绝的承诺。

是的-您创建了承诺,但从未处理过它的错误(比如在中的异常,从未执行。

(注意,这不是“拒绝最后的承诺”,而是永远是第二个等待的承诺。

那是因为异步函数的try/catch块没有内置机制以这种方式捕获多个拒绝吗?

在顺序代码中,不可能有多个异常,因此想出额外的语法来处理这些异常是很困难的。

我是否仍然需要在异步函数内部使用来确保错误得到正确处理?

是的,正是这样。如果希望并行等待多个承诺,则应始终使用关键字只是下面调用的糖。

你应该写

async function asyncParallel() {
  try {
    let [val1, val2] = await Promise.all([timeoutOne(), timeoutTwo()]);
    console.log(`All done with ${val1} ${val2}`)
  } catch(err) {
    console.log(err)
  }
}

在这两种情况下,只有首先返回的promise记录错误。我知道在一些promise库中有一种记录所有错误的方法(例如bluebird中的“settle”方法,但是,我不确定在原生Promises中是否有类似于此方法的方法?

不,没有。的特性对于您自己使用实现来说是微不足道的,可以使用您想要的任何值:

async function asyncParallel() {
  try {
    let [stat1, stat2] = await Promise.all([
        timeoutOne().then(() => "one fulfilled", () => "one rejected"), 
        timeoutTwo().then(() => "two fulfilled", () => "two rejected")
    ]);
    console.log(`All settled with ${stat1} ${stat2}`)
  } catch(err) {
    console.log(err)
  }
}