Асинхронный код ожидания не работает с forEach - PullRequest
1 голос
/ 09 мая 2019

У меня есть этот код, который при запуске будет запускать 'one' и 'two' в указанном порядке.

Таким образом, приведенный ниже код работает нормально.

(async () => {

  await runit('one').then(res => {
    console.info(res);
  });

  await runit('two').then(res => {
    console.info(res);
  });

})();

Теперь яЯ хотел сделать то же самое, но вместо этого в цикле, поэтому я сделал это:

const arr = ['one', 'two'];
  arr.forEach(element => {
    (async () => {
      await runit(element).then(res => {
      console.info(res);
    });
  })();
});

Хотя это похоже на тот же код, он больше не работает в том же порядке, что и код вверху.

Как я могу это исправить?

Ответы [ 3 ]

4 голосов
/ 09 мая 2019

Вы можете достичь того же, используя функцию promise.all, как показано ниже.

const arr = ['one', 'two'];
const promises = [];
  arr.forEach(element => {
      promises.push(runit(element));
  });

Promise.all(promises).then(results => {
    console.log(results)//you will get results here.
});
2 голосов
/ 09 мая 2019

Это не ждет, потому что выполняемая вами функция асинхронная, вы фактически говорите ей не ждать.Чтобы исправить это, вы можете сделать простой цикл:

for (let i = 0; i < arr.length; i++) {
  const item = arr[i];
  await runit(item).then(res => {
    console.info(res);
  });
}

или использовать карту и Promise.all:

const promises = arr.map(item => runit(item)));
const values = Promise.all(promises);
values.forEach(res => console.info(res))

Последний вариант предпочтительнее.

1 голос
/ 10 мая 2019

Избегайте forEach с await. Это не будет работать правильно.

forEach игнорирует все результаты функции обратного вызова, которую он принимает. Если вы передадите ей функцию async или любую другую функцию, возвращающую обещание, все возвращенные обещания останутся необработанными.

Вместо этого используйте встроенные циклы for. Чтобы соответствовать вашему нецикличному коду, который одновременно запускает только один элемент, выполните:

for (const element of ['one', 'two']) {
  console.log(await runit(element));
}

Это существенно отличается от других ответов с Promise.all. Promise.all ожидает массового выполнения нескольких обещаний, что подразумевает, что все идет параллельно.

Чтобы запустить вещи параллельно, выполните:

for (const res of await Promise.all(['one', 'two'].map(runit)) {
  console.log(res);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...