Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про JavaScript: forEach, async, await, promise, array iteration

Почему forEach не работает с async/await?

Этот вопрос проверяет понимание асинхронного выполнения в JavaScript и различий между методами итерации массивов.

Короткий ответ

Метод forEach не предназначен для работы с асинхронными функциями, потому что он не ожидает разрешения промисов, возвращаемых колбэком. Он просто запускает каждую асинхронную операцию и сразу переходит к следующей, не дожидаясь её завершения. В результате операции выполняются параллельно (или в случайном порядке), а не последовательно, и нельзя корректно обработать результаты или ошибки. Для последовательного выполнения асинхронных операций следует использовать обычный цикл for...of с await.

Длинный ответ

Метод forEach — это синхронный итератор массивов в JavaScript. Когда вы передаёте в него асинхронную функцию (помеченную async), она возвращает промис, но forEach не умеет "ждать" этот промис. Вместо этого он немедленно вызывает следующую итерацию, что приводит к параллельному запуску всех асинхронных операций без гарантии порядка завершения.

Как работает forEach с async

Рассмотрим пример:

const delays = [1000, 500, 2000];

async function asyncTask(ms) {
  await new Promise(resolve => setTimeout(resolve, ms));
  console.log(`Done after ${ms}ms`);
}

console.log('Start');
delays.forEach(async (ms) => {
  await asyncTask(ms);
});
console.log('End');

Вывод будет: "Start", "End", "Done after 500ms", "Done after 1000ms", "Done after 2000ms". Обратите внимание, что "End" появится сразу, потому что forEach не ждёт завершения асинхронных задач. Задачи выполняются параллельно, и порядок вывода зависит от времени задержки, а не от порядка в массиве.

Почему это проблема

  • Отсутствие последовательности: Невозможно гарантировать, что операции выполнятся одна за другой.
  • Невозможность обработки ошибок: Если одна операция завершится с ошибкой, forEach не прервётся, и ошибку будет сложно поймать.
  • Нельзя использовать результаты: Поскольку операции запускаются "и улетают", собрать их результаты в массив после forEach не получится — массив будет пустым.

Альтернативы для асинхронных операций

Для последовательного выполнения используйте цикл for...of:

async function processSequentially() {
  for (const ms of delays) {
    await asyncTask(ms); // Ждём завершения каждой
  }
}

Для параллельного выполнения с сохранением результатов подходит Promise.all с map:

async function processInParallel() {
  const promises = delays.map(ms => asyncTask(ms));
  await Promise.all(promises); // Ждём все сразу
}

Вывод: Используйте forEach только для синхронных операций. Для асинхронного кода выбирайте for...of (последовательно) или Promise.all с map (параллельно), в зависимости от задачи.

Уровень

  • Рейтинг:

    4

  • Сложность:

    3

Навыки

  • JavaScript

    JavaScript

Ключевые слова

#forEach

#async

#await

#promise

#array iteration

Подпишись на React Developer в телеграм