Promise.allSettled() у JavaScript
Promise.allSettled() це статичний метод, який приймає масив (або інший ітерований об'єкт) промісів і повертає новий проміс, що виконується, коли всі передані проміси завершаться. Не має значення, чи завершились вони успішно (fulfilled), чи з помилкою (rejected): метод чекає на усі результати, а не лише на успішні.
Теорія
TL;DR
Promise.allSettled(iterable)чекає, поки всі проміси завершаться будь-яким чином.- Повернений проміс завжди переходить у стан
fulfilled, він не відхиляється ніколи. - Значення це масив об'єктів
{status, value}або{status, reason}у порядку входу. Promise.all()натомість відхиляється на першому жrejectі губить решту результатів.- Типове застосування: масове завантаження даних, паралельна валідація, пакетне надсилання запитів.
Швидкий приклад
const p1 = Promise.resolve('Успішно');
const p2 = Promise.reject('Помилка');
const p3 = Promise.resolve('Ще одне');
Promise.allSettled([p1, p2, p3])
.then(results => console.log(results));Вивід:
[
{ status: "fulfilled", value: "Успішно" },
{ status: "rejected", reason: "Помилка" },
{ status: "fulfilled", value: "Ще одне" }
]Усі проміси завершились, метод не «впав», а повернув повне зведення: хто виконався, а хто впав.
Синтаксис:
Promise.allSettled(iterable)Повертає новий проміс, який завжди переходить у стан fulfilled і віддає масив об'єктів з результатами.
Структура результату
Кожен елемент масиву це об'єкт з однаковим набором полів:
| Поле | Коли з'являється | Значення |
|---|---|---|
status | завжди | "fulfilled" або "rejected" |
value | якщо fulfilled | результат проміса |
reason | якщо rejected | причина помилки |
Порядок елементів відповідає порядку вхідних промісів, тому результат легко зіставити з початковим списком за індексом.
Коли використовувати Promise.allSettled()
- Коли важливо дочекатися завершення всіх операцій, навіть якщо частина з них завершиться з помилкою.
- Коли потрібно зібрати всі результати та помилки разом, в одному звіті.
- Наприклад, при масовому завантаженні даних, паралельній валідації, пакетному надсиланні запитів, очищенні даних тощо.
Відмінність від Promise.all()
| Характеристика | Promise.all() | Promise.allSettled() |
|---|---|---|
| Коли завершиться | Тільки якщо всі проміси успішні | Коли всі проміси завершаться (з будь-яким результатом) |
| Що повертає | Масив значень value | Масив об'єктів {status, value/reason} |
| Поведінка при помилці | «Падає» на першому ж reject | Не падає, чекає на всіх |
| Стан поверненого проміса | Може бути fulfilled або rejected | Завжди fulfilled |
| Для чого використовують | Коли важливо, щоб усе пройшло успішно | Коли важливо отримати звіт про всі результати |
Приклад порівняння:
const a = Promise.resolve('A');
const b = Promise.reject('Помилка');
const c = Promise.resolve('C');
// Promise.all
Promise.all([a, b, c])
.then(console.log)
.catch(err => console.error('Promise.all:', err));
// Promise.allSettled
Promise.allSettled([a, b, c])
.then(console.log);Вивід:
Promise.all: Помилка
[
{ status: 'fulfilled', value: 'A' },
{ status: 'rejected', reason: 'Помилка' },
{ status: 'fulfilled', value: 'C' }
]Promise.all() зупинився на помилці, а Promise.allSettled() дочекався всіх і повернув повний звіт.
Практичний приклад
Уявіть, що потрібно завантажити дані з кількох джерел, і навіть якщо одне недоступне, решта все одно потрібні:
const urls = ['/user', '/posts', '/comments'];
const requests = urls.map(url => fetch(url));
Promise.allSettled(requests)
.then(results => {
results.forEach((res, i) => {
if (res.status === 'fulfilled') {
console.log(`${urls[i]}: OK`);
} else {
console.warn(`${urls[i]}: помилка`);
}
});
});Так ви отримуєте підсумок по всіх запитах, навіть якщо один із них «впав».
Проста аналогія:
Уявіть, що ви замовили три доставки:
Promise.all(): якщо хоча б одна доставка не дійшла, ви одразу засмучуєтесь і не чекаєте на решту.Promise.allSettled(): ви чекаєте на всіх кур'єрів, навіть якщо хтось прийшов без посилки, щоб знати, що сталося з кожною доставкою.
Підсумкова таблиця:
| Метод | Поведінка при помилці | Що повертає | Коли завершиться |
|---|---|---|---|
Promise.all() | «Падає» на першому reject | Масив успішних значень | Коли всі успішні |
Promise.allSettled() | Не «падає» ніколи | Масив {status, value/reason} | Коли всі завершені |
Типові помилки
- Чіпляти
.catch()і чекати, що він спрацює. Проміс відallSettled()не відхиляється, тому помилки треба шукати в елементах масиву зіstatus === 'rejected', інакше збій пройде непоміченим. - Плутати
valueіreason. У відхиленого елемента немаєvalue, у виконаного немаєreason: спершу перевіряйтеstatus. - Думати, що
allSettled()робить код стійкішим сам собою. Він лише збирає звіт, а логіку повторів чи деградації ви пишете самі. - Забувати про HTTP помилки у
fetch.fetchвідхиляється лише на мережевій помилці, тому відповідь зі статусом 500 потрапить уfulfilled, іres.okтреба перевіряти окремо. - Брати
allSettled()там, де потрібен fail-fast. Якщо перший збій робить решту роботи безглуздою,Promise.all()завершиться швидше і заощадить ресурси.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.