TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
JavaScript Ready | Программирование

5 Oct, 14:07

Открыть в Telegram Поделиться Пожаловаться

Почему forEach() не ждёт async-функцию?

forEach() не учитывает возвращаемое значение callback и не содержит механизма ожидания Promise. Поэтому передача async-callback не меняет модель выполнения метода: forEach() синхронно запускает callback для каждого элемента, не ожидая завершения созданных им асинхронных операций:
const users = [1, 2, 3];

users.forEach(async (id) => {
await saveUser(id);
});

console.log("Готово");

"Готово" будет выведено до завершения saveUser(). Каждый вызов async-callback возвращает Promise, но forEach() эти Promise не ожидает и не собирает.

Если операции должны выполняться последовательно, ожидание необходимо сделать частью самого цикла. Для этого подходит for...of с await:
for (const id of users) {
await saveUser(id);
}

console.log("Готово");

Следующая итерация начнётся только после завершения предыдущей. Такой вариант нужен, когда важен порядок выполнения или операции зависят друг от друга.

Для независимых операций можно сформировать массив Promise и дождаться их через Promise.all():
await Promise.all(
users.map((id) => saveUser(id))
);

console.log("Готово");

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

Есть и важное следствие для обработки ошибок: внешний try...catch вокруг forEach() не перехватит последующее отклонение Promise из async-callback:
try {
users.forEach(async (id) => {
await saveUser(id);
});
} catch (error) {
console.error(error);
}

Для управляемой обработки ошибки необходимо ожидать Promise, представляющий выполнение асинхронных операций:
try {
await Promise.all(
users.map((id) => saveUser(id))
);
} catch (error) {
console.error(error);
}

🔥 Проблема не в async внутри forEach(), а в контракте самого метода: forEach() игнорирует возвращаемое значение callback и не ожидает Promise. Для последовательного выполнения используйте for...of с await, для конкурентного выполнения независимых операций — Promise.all().

📣 JS Ready | #практика

755 0 14 21
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot