首页 文章

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

提问于
浏览
6

在异步函数(javaScript - node v8.4.0)中等待多个promises抛出拒绝错误后,我遇到了捕获所有错误的问题 .

参考以下javaScript:

作为参考,函数timeoutOne()和timeoutTwo()只返回一个本机promise,它分别在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中的“sett”方法),但是,我不确定在本机承诺中是否存在这种方法的类似物?

此外,如果两个promise都拒绝,则asyncParallel()会记录一个未被捕获的错误,其中包含拒绝最后的承诺 . 那是因为async函数的try / catch块没有内置机制来以这种方式捕获多次拒绝吗?

如果承诺解决了,两种情况下的一切都是一样的 . 它只是当两者都拒绝时,Promise.all处理错误,而异步函数版本声明其中一个未处理的promise错误将在未来版本的节点中使进程崩溃 .

无论如何,try / catch是否正确处理此类错误?或者我仍然需要在异步函数中使用Promise.all以确保错误得到正确处理?

1 回答

  • 6

    如果两个promise都拒绝,则asyncParallel()会记录一个未被捕获的错误,其中包含拒绝最后的承诺 .

    是的 - 您创建了 timeoutTwo() 承诺但从未处理过它的错误(比如在 await 中使用它) . 由于 await res1 中的异常, await res2 从未执行过 .

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

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

    在顺序代码中,不能有多个异常,因此提出额外的语法来处理它们会很困难 .

    我是否仍需要在异步函数中使用Promise.all以确保错误得到正确处理?

    是的,正是如此 . 如果要并行等待多个promise,则应始终使用 Promise.all . await 关键字只是以下 .then() 调用的糖 .

    你应该写

    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中的“sett”方法),但是,我不确定在本机承诺中是否存在这种方法的类似物?

    不,没有 . 使用 then 实现自己 settle 的特性是微不足道的,可以使用您想要的任何值:

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

相关问题