【问题标题】:Catching All Promise Rejections in an Async Function in JavaScript在 JavaScript 中的异步函数中捕获所有 Promise 拒绝
【发布时间】:2018-03-24 13:37:58
【问题描述】:

当多个 Promise 在异步函数(javaScript - 节点 v8.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”方法),但是,我不确定在原生 Promise 中是否有类似这种方法的方法?

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

如果 Promise 得到解决,这两种情况下的一切都是一样的。只是当两者都被拒绝时,Promise.all 会处理错误,并且 async 函数版本指出未处理的 Promise 错误之一将在未来版本的节点中使进程崩溃。

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

【问题讨论】:

    标签: javascript error-handling async-await es6-promise


    【解决方案1】:

    如果两个 Promise 都被拒绝,那么 asyncParallel() 会记录一个未捕获的错误以及最后拒绝的 Promise。

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

    (请注意,它不是“最后拒绝的承诺”,而是第二个等待的承诺)。

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

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

    我还需要在异步函数中使用Promise.all 来确保错误得到正确处理吗?

    是的,正是如此。如果你想并行等待多个 Promise,你应该总是使用Promise.allawait 关键字只是后续 .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 中的“settle”方法),但是,我不确定在原生 Promise 中是否有类似这种方法的方法?

    不,没有。 settle 的特性很容易使用 then 实现自己,具有您想要的任何值:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-10
      • 2015-10-06
      • 2018-01-07
      • 1970-01-01
      相关资源
      最近更新 更多