Не удалось отловить ошибку в ожидании цикла - PullRequest
0 голосов
/ 17 апреля 2019

Я читал о "для ожидания цикла", как , описанное в MDN . Это выглядит впечатляюще, поэтому я немного поиграл с некоторым кодом, но я удивительно не в состоянии отловить ошибки, которые там появляются.

'use strict';

const main = async() => {
  const bar = [];
  bar.push(new Promise((res) => { setTimeout(() => res(1), 1200); }));
  bar.push(new Promise((res) => { setTimeout(() => res(2), 800); }));
  bar.push(new Promise((res, rej) => { setTimeout(() => rej(3), 200); }));

  try {
    for await (const foo of bar) {
      console.log('hey', foo);
    }
  } catch (err) {
    console.error('err', err);
  }
};

main();

Мой вывод, как я и ожидал, в основном. Но я не могу понять, почему я получаю UnhandledPromiseRejection? Разве я не уловил эту ошибку?

$> node await-loop.js 
(node:10704) UnhandledPromiseRejectionWarning: 3
(node:10704) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:10704) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
hey 1
hey 2
err 3
(node:10704) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)

Может кто-нибудь помочь мне понять и написать здесь правильную фразу? Я что-то упустил?

1 Ответ

0 голосов
/ 17 апреля 2019

UnhandledPromiseRejection

Разве я не уловил эту ошибку?

Теоретически, да. (Хорошо, для чего нужен блок catch?)

Технически нет.

Main Stack
|  try             |
|                  |
|    await bar[0]  | <-- waiting to resolve till sometime after 1200
|                  |
|  catch           |
|                  |

После (приблизительно) 200 миллисекунд :

бар [2] отклонен и помещен в очередь, но ожидание не дало, потому что он все еще ждал, пока бар [0] даст, что происходит только после 1200 миллис

Таким образом, на момент отклонения бара [2] блок catch отсутствовал для обработки rejected promise. Посмотрите вышеупомянутый стек и обратите внимание, что try..catch и bar[2] не находятся в одном стеке во время отклонения, ну, по крайней мере, по отношению к компилятору (или концептуально для javascript).

Но вы замечаете: err 3, который ловит блок catch, когда, наконец, ожидают, дает bar[2]

Если вы измените порядок обещаний и поместите отклоненное обещание в качестве первого элемента в массиве, вы увидите, что блок catch работал хорошо.

Или ждем по-другому:

// unhandled rejection
try {
  await bar[0]
  await bar[1]
  await bar[2]
} catch (e) {
  console.error('error', e)
}

// Catch successfull
try {
  await bar[2]
  await bar[0]
  await bar[1]
} catch (e) {
  console.error('error', e)
}

Обновление:

Лучшим подходом было бы использовать Promise.all, он работает без сбоев.

try {
  const datas = await Promise.all(bar)
} catch (e) {
  console.error(e)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...