Skip to main content
Практика завдань

Promise.all, promise.race, promise.allsettled, promise.any

Статичні методи Promise

JavaScript надає чотири основні статичні методи для роботи з кількома промісами одночасно:

  • Promise.all()
  • Promise.race()
  • Promise.allSettled()
  • Promise.any()

Кожен з них вирішує різні завдання. Розглянемо їх детальніше.


Promise.all()

Чекає, поки всі проміси будуть виконані. Якщо хоча б один буде відхилений — весь результат буде відхилений.

Синтаксис

javascript
Promise.all(iterable)

Поведінка

  • ✅ Повертає масив результатів, якщо всі проміси були успішно виконані
  • ❌ Відхиляється з помилкою першого відхиленого промісу
  • Порядок результатів відповідає порядку промісів

Приклад успішного виконання

javascript
const promise1 = Promise.resolve(10); const promise2 = Promise.resolve(20); const promise3 = Promise.resolve(30); Promise.all([promise1, promise2, promise3]) .then(results => { console.log(results); // [10, 20, 30] });

Приклад відхилення

javascript
const promise1 = Promise.resolve(10); const promise2 = Promise.reject('Error!'); const promise3 = Promise.resolve(30); Promise.all([promise1, promise2, promise3]) .then(results => { console.log(results); }) .catch(error => { console.log(error); // "Error!" // promise3 буде проігноровано });

Коли використовувати?

  • Завантаження кількох незалежних ресурсів одночасно
  • Усі запити потрібні для продовження роботи
  • Потрібно дочекатися завершення всіх операцій
javascript
async function loadUserData(userId) { const [user, posts, comments] = await Promise.all([ fetchUser(userId), fetchPosts(userId), fetchComments(userId) ]); return { user, posts, comments }; }

Важливо:

Якщо один проміс відхиляється, інші проміси продовжують виконуватися, але їх результати будуть проігноровані.


Promise.race()

Повертає результат першого виконаного промісу (успішно або з помилкою).

Синтаксис

javascript
Promise.race(iterable)

Поведінка

  • Завершується, як тільки будь-який проміс виконується
  • Повертає результат або помилку першого виконаного промісу
  • Інші проміси ігноруються

Приклад

javascript
const slow = new Promise(resolve => { setTimeout(() => resolve('Slow'), 2000); }); const fast = new Promise(resolve => { setTimeout(() => resolve('Fast'), 500); }); Promise.race([slow, fast]) .then(result => { console.log(result); // "Fast" });

Приклад помилки

javascript
const success = new Promise(resolve => { setTimeout(() => resolve('Success'), 2000); }); const failure = new Promise((resolve, reject) => { setTimeout(() => reject('Error'), 500); }); Promise.race([success, failure]) .then(result => console.log(result)) .catch(error => console.log(error)); // "Error"

Коли використовувати?

  • Таймаути: скасувати операцію, якщо вона триває занадто довго
  • Резервні варіанти: спробувати кілька джерел даних
  • Гонка запитів: використовувати найшвидшу відповідь
javascript
// Таймаут запиту function fetchWithTimeout(url, timeout = 5000) { return Promise.race([ fetch(url), new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), timeout) ) ]); } fetchWithTimeout('/api/data', 3000) .then(response => response.json()) .catch(error => console.error(error));

Promise.allSettled()

Чекає, поки всі проміси завершаться (успішно або з помилкою) і повертає їх статуси.

Синтаксис

javascript
Promise.allSettled(iterable)

Поведінка

  • ✅ Завжди виконується (ніколи не відхиляється)
  • Повертає масив об'єктів з результатами кожного промісу
  • Кожен об'єкт містить status і value / reason

Формат результату

javascript
[ { status: 'fulfilled', value: result }, { status: 'rejected', reason: error } ]

Приклад

javascript
const promises = [ Promise.resolve(10), Promise.reject('Error'), Promise.resolve(30) ]; Promise.allSettled(promises) .then(results => { console.log(results); /* [ { status: 'fulfilled', value: 10 }, { status: 'rejected', reason: 'Error' }, { status: 'fulfilled', value: 30 } ] */ });

Обробка результатів

javascript
const results = await Promise.allSettled([ fetch('/api/users'), fetch('/api/posts'), fetch('/api/comments') ]); const successful = results .filter(r => r.status === 'fulfilled') .map(r => r.value); const failed = results .filter(r => r.status === 'rejected') .map(r => r.reason); console.log('Успішно:', successful.length); console.log('Не вдалося:', failed.length);

Коли використовувати?

  • Потрібні результати всіх операцій, навіть якщо деякі не вдалися
  • Агрегація даних з кількох джерел
  • Часткове завантаження даних (показати, що завантажено)
javascript
async function loadDashboard() { const [userResult, statsResult, notificationsResult] = await Promise.allSettled([ fetchUser(), fetchStats(), fetchNotifications() ]); return { user: userResult.status === 'fulfilled' ? userResult.value : null, stats: statsResult.status === 'fulfilled' ? statsResult.value : null, notifications: notificationsResult.status === 'fulfilled' ? notificationsResult.value : [] }; }

ES2020:

Promise.allSettled() був доданий в ES2020 і підтримується всіма сучасними браузерами.


Promise.any()

Повертає перший успішно виконаний проміс. Відхиляється лише якщо всі проміси відхилені.

Синтаксис

javascript
Promise.any(iterable)

Поведінка

  • ✅ Виконується з результатом першого успішного промісу
  • ❌ Відхиляється лише якщо всі проміси відхилені (з AggregateError)
  • Ігнорує відхилені проміси, якщо є хоча б один успішний

Приклад

javascript
const promises = [ Promise.reject('Error 1'), Promise.resolve('Success!'), Promise.reject('Error 2') ]; Promise.any(promises) .then(result => { console.log(result); // "Success!" });

Приклад повного відхилення

javascript
const promises = [ Promise.reject('Error 1'), Promise.reject('Error 2'), Promise.reject('Error 3') ]; Promise.any(promises) .catch(error => { console.log(error); // AggregateError: All promises were rejected console.log(error.errors); // ['Error 1', 'Error 2', 'Error 3'] });

Коли використовувати?

  • Резервні варіанти: спробувати кілька джерел даних
  • Потрібен хоча б один успішний результат
  • Робота з ненадійними API (спробувати кілька серверів)
javascript
// Завантажити зображення з резервних серверів async function loadImage(imageName) { const servers = [ `https://cdn1.example.com/${imageName}`, `https://cdn2.example.com/${imageName}`, `https://cdn3.example.com/${imageName}` ]; try { const imageUrl = await Promise.any( servers.map(url => fetch(url).then(r => { if (!r.ok) throw new Error('Failed'); return url; })) ); return imageUrl; } catch (error) { console.error('Усі сервери недоступні'); } }

ES2021:

Promise.any() був доданий в ES2021.


Таблиця порівняння

МетодЗавершується колиУспішний результатРезультат помилки
Promise.allУсі виконані АБО перший відхиленийМасив усіх результатівПерша помилка
Promise.raceПерший виконанийПерший результатПерша помилка
Promise.allSettledУсі завершеніМасив {status, value/reason}Ніколи не відхиляється
Promise.anyПерший виконаний АБО всі відхиленіПерший успішний результатAggregateError

Практичні приклади

Завантаження з таймаутом і повтором

javascript
async function fetchWithRetry(url, retries = 3, timeout = 5000) { for (let i = 0; i < retries; i++) { try { const result = await Promise.race([ fetch(url), new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), timeout) ) ]); return result; } catch (error) { if (i === retries - 1) throw error; console.log(`Спроба ${i + 1} не вдалася, повторюємо...`); } } }

Паралельне завантаження з обмеженням

javascript
async function fetchWithLimit(urls, limit = 3) { const results = []; const executing = []; for (const url of urls) { const promise = fetch(url).then(r => r.json()); results.push(promise); if (limit <= urls.length) { const executing_promise = promise.then(() => executing.splice(executing.indexOf(executing_promise), 1) ); executing.push(executing_promise); if (executing.length >= limit) { await Promise.race(executing); } } } return Promise.all(results); }

Часткове завантаження даних

javascript
async function loadPageData() { const results = await Promise.allSettled([ fetchCriticalData(), // Обов'язкові дані fetchOptionalWidget1(), // Додаткові віджети fetchOptionalWidget2(), fetchOptionalWidget3() ]); // Якщо критичні дані не завантажилися - показати помилку if (results[0].status === 'rejected') { throw new Error('Не вдалося завантажити сторінку'); } return { critical: results[0].value, widgets: results.slice(1) .filter(r => r.status === 'fulfilled') .map(r => r.value) }; }

Висновок

  • Promise.all() — все або нічого (паралельне завантаження обов'язкових даних)
  • Promise.race() — перший виграє (таймаути, гонка запитів)
  • Promise.allSettled() — результат кожного (часткове завантаження, агрегація)
  • Promise.any() — перший успішний (резервні сервери, резервні варіанти)

На співбесідах:

Звичайні запитання:

  • У чому різниця між Promise.all і Promise.allSettled?
  • Коли використовувати Promise.race проти Promise.any?
  • Що станеться, якщо передати порожній масив кожному методу?
  • Як обробляти часткові помилки при завантаженні даних?

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань