4

Promise.all([iterable])是全有或全无,这意味着它返回的 Promise 在 iterable 中的每个 Promise 解析时解析,或者一旦其中一个 Promise 拒绝就拒绝,原因是第一个 Promise 拒绝(doc)。

但是,如果可迭代的多个 promise 被拒绝,会发生什么?

在 VSCode 中,我尝试了以下示例,并故意使foo()bar()承诺都失败。当我在 VSCode 中调试时,我在 * catch(err => Promise.reject('error query bar()'))* 上收到一个错误,说发生了异常,我不明白为什么。

我认为这是因为当我调用 Promise.reject 时, Promise.all 已经收到来自 foo 函数的拒绝,该函数也失败了,但目前尚不清楚发生了什么。

如果我在调试选项中禁用“未捕获的异常”断点,则该异常不再显示。

这里到底发生了什么?

function foo() {
  return pool.query('insert_test into test (value) values (20)')
    .then(() => client.query('insert into test (value) values (21)'))
    .catch(err => Promise.reject('error query bar()'))
}

function bar() {
  return pool.query('insert_test into test (value) values (20)')
    .then(() => client.query('insert into test (value) values (21)'))
    .catch(err => Promise.reject('error query bar()'))
 }

 Promise.all([foo(), bar()])
   .then(results => {
     console.log(results)
   })
   .catch(err => {
     console.log(err)
   });

这是我在启用未捕获异常时看到的屏幕截图。 在此处输入图像描述

4

2 回答 2

4

但是,如果可迭代的多个 promise 被拒绝,会发生什么?

第一个拒绝获胜并得到拒绝Promise.all承诺的理由。这里的“首先”意味着“最早发生”,如果在Promise.all访问它们时承诺已经被拒绝,则迭代顺序很重要。

随后的拒绝将被忽略。

如果我在调试选项中禁用“未捕获的异常”断点,则该异常不再显示。

这很奇怪。被忽略的拒绝不应导致未处理的拒绝(或未捕获的异常)。

于 2017-12-01T12:42:17.157 回答
-1

@smellyarmpits如果你想防止在第一个承诺被拒绝后被拒绝的剩余承诺的未捕获异常,因此在Promise.all被拒绝后,可以尝试自定义实现 Promise.all 来包装像这样的原始承诺(打字稿):

  const promiseAll = async (promises: Promise<any>[]) => {
    let oneHasRejected = false
    const onReject = (err: any) => {
      if (oneHasRejected) {
        oneHasRejected = true
        return Promise.reject(err)
      } else {
        return Promise.resolve()
      }
    }
    return Promise.all(promises.map((p) => p.then((r) => r, onReject)))
  }
于 2019-07-01T12:38:46.803 回答