Promise.all, race, allSettled, any: работа с группой промисов

Зачем нужны методы для работы с группой промисов? 🤔

Представьте, что вы отправили несколько асинхронных запросов к API и хотите:

  • Получить все ответы одновременно (Promise.all)
  • Узнать, какой промис выполнится первым (Promise.race)
  • Обработать результаты всех промисов, даже с ошибками (Promise.allSettled)
  • Дождаться первого успешного промиса (Promise.any)

Эти методы — мощные инструменты для управления асинхронным кодом. Разберём каждый на примерах!


Promise.all: «Все или ничего» 🎯

Ожидает выполнения всех промисов. Если хоть один отклонён — сразу возвращает ошибку.

const promises = [
  fetch('/api/users'),
  fetch('/api/posts'),
  fetch('/api/comments')
];

Promise.all(promises)
  .then(([users, posts, comments]) => {
    console.log('Все данные загружены:', { users, posts, comments });
  })
  .catch(error => {
    console.error('Один из запросов провалился:', error);
  });

🔥 Важно: Порядок результатов соответствует порядку промисов в массиве, даже если они выполняются в разное время.


Promise.race: Гонка промисов 🏁

Возвращает результат первого завершившегося промиса (не важно, успешного или с ошибкой).

const timeout = ms => new Promise(
  (_, reject) => setTimeout(() => reject('Timeout!'), ms)
);

const fetchData = fetch('/api/data');

Promise.race([fetchData, timeout(5000)])
  .then(data => console.log('Данные получены:', data))
  .catch(error => console.error('Ошибка или таймаут:', error));

💡 Идея: Часто используют для реализации таймаутов или выбора самого быстрого источника данных.


Promise.allSettled: Без исключений 🛡️

Ждёт завершения всех промисов и возвращает массив с результатами, включая ошибки.

const promises = [
  Promise.resolve('Успех'),
  Promise.reject('Ошибка'),
  Promise.resolve('Ещё успех')
];

Promise.allSettled(promises)
  .then(results => {
    results.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        console.log(`Промис ${index}:`, result.value);
      } else {
        console.log(`Промис ${index} failed:`, result.reason);
      }
    });
  });

📌 Особенность: Не имеет .catch() — всегда «успешный» промис с массивом результатов.


Promise.any: Первый успешный 🏆

Ожидает первый успешно выполненный промис. Если все отклонены — возвращает AggregateError.

const apis = [
  fetch('https://backup-api-1/data'),
  fetch('https://backup-api-2/data'),
  fetch('https://primary-api/data')
];

Promise.any(apis)
  .then(data => console.log('Первый успешный ответ:', data))
  .catch(errors => {
    console.error('Все API упали:', errors.errors);
  });

🚀 Сценарий: Отлично подходит для резервных API-вызовов — используем самый быстрый работающий источник.


Сравнение методов 📊

Метод Ждёт Успех Ошибка
Promise.all Все Массив всех результатов Первая ошибка
Promise.race Первый Результат первого завершённого Ошибка первого завершённого
Promise.allSettled Все Массив статусов всех промисов Не бывает (всегда успех)
Promise.any Первый успешный Результат первого успешного AggregateError (если все упали)

Практика: Кейс из реальной жизни 💼

1. Параллельная загрузка изображений:

const loadImage = url => fetch(url).then(r => r.blob());

Promise.all([
  loadImage('cat.jpg'),
  loadImage('dog.jpg')
]).then(blobs => {
  blobs.forEach(blob => {
    const img = new Image();
    img.src = URL.createObjectURL(blob);
    document.body.append(img);
  });
});
Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео