Несколько отклонений от обещаний в Promise.all, что именно происходит?

Promise.all([iterable]) - это все или ничего, что означает, что обещание, которое он возвращает, разрешается, когда каждое обещание в итерируемом разрешается или отклоняется, как только одно из обещаний отклоняется, по причине первого отклонения обещания ( doc).

Но что произойдет, если несколько обещаний повторяемого отклонения?

В VSCode я попробовал следующий пример и намеренно сделал обещания foo() и bar() не выполненными. Когда я отлаживаю в VSCode, я получаю сообщение об ошибке * catch(err => Promise.reject('error query bar()'))*, говорящее о том, что произошло исключение, и я не понимаю, почему.

Я думаю, это потому, что когда я вызываю Promise.reject, Promise.all уже получил отклонение от функции foo, которая также не работает, но неясно, что происходит.

Если я отключу точку останова "Uncaught Exceptions" в параметрах отладки, исключение больше не будет отображаться.

Что именно здесь происходит?

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

Это скриншот того, что я вижу с включенными исключениями Uncaught.

1 ответ

Но что произойдет, если несколько обещаний повторяемого отклонения?

Первый отказ выигрывает и получает причину отклонить Promise.all Обещаю. "Первый" здесь означает "случается раньше", если обещания уже были отклонены, когда Promise.all посещает их, порядок итераций важен.

Последующие отклонения будут игнорироваться.

Если я отключу точку останова "Uncaught Exceptions" в параметрах отладки, исключение больше не будет отображаться.

Это странно. Игнорируемое отклонение не должно вызывать необработанное отклонение (или необученное исключение).

@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)))
  }
Другие вопросы по тегам