Promise.allSettled() нужен, чтобы дождаться завершения всех промисов независимо от результата. Метод вызывается у Promise, принимает набор значений и возвращает новый промис, который завершится только после того, как каждый элемент либо выполнится успешно, либо завершится с ошибкой.
Синтаксис
Базовая запись выглядит так:
Promise.allSettled(iterable)
Где:
iterable- итерируемый набор значений, чаще всего массив
Обычно в Promise.allSettled() передают массив промисов, но внутри могут быть и обычные значения.
Что возвращает Promise.allSettled()
Метод всегда возвращает объект Promise.
Если всё прошло штатно на уровне самого вызова, результатом будет массив объектов со статусом каждого элемента.
const promise = Promise.allSettled([
Promise.resolve("ok"),
Promise.reject(new Error("boom")),
]);
console.log(promise instanceof Promise); // true
promise.then((results) => {
console.log(results);
});
Элементы результата имеют такой вид:
{ status: "fulfilled", value: ... }{ status: "rejected", reason: ... }
Простой пример
Promise.allSettled([
Promise.resolve("Пользователь"),
Promise.reject(new Error("Ошибка загрузки")),
]).then((results) => {
console.log(results);
});
Примерный результат:
[
{ status: "fulfilled", value: "Пользователь" },
{ status: "rejected", reason: Error("Ошибка загрузки") }
]
Это удобно, когда нужно получить картину по всем операциям сразу, а не падать на первой ошибке.
Promise.allSettled() ждёт все элементы до конца
Это главный смысл метода.
Даже если часть промисов завершится с ошибкой, итоговый результат всё равно будет только после завершения всех элементов.
const userPromise = Promise.resolve("Анна");
const settingsPromise = Promise.reject(new Error("Нет настроек"));
Promise.allSettled([userPromise, settingsPromise]).then((results) => {
console.log(results);
});
То есть здесь не будет раннего падения, как у Promise.all().
Порядок результатов сохраняется по входному массиву
Это очень важный нюанс.
Promise.allSettled() не сортирует результат по скорости выполнения. Он сохраняет порядок именно таким, каким элементы были переданы.
const first = new Promise((resolve) => {
setTimeout(() => resolve("first"), 50);
});
const second = new Promise((_, reject) => {
setTimeout(() => reject("second error"), 10);
});
Promise.allSettled([first, second]).then((results) => {
console.log(results[0].status); // "fulfilled"
console.log(results[1].status); // "rejected"
});
Хотя второй элемент завершился раньше, в массиве он всё равно остался на второй позиции.
Обычные значения тоже работают
Это ещё один полезный момент.
В Promise.allSettled() можно передавать не только промисы, но и обычные значения.
Promise.allSettled([1, Promise.resolve(2), Promise.reject("x")]).then((results) => {
console.log(results);
});
Примерный результат:
[
{ status: "fulfilled", value: 1 },
{ status: "fulfilled", value: 2 },
{ status: "rejected", reason: "x" }
]
Обычные значения будут считаться успешно завершёнными.
Ошибка внутри одного промиса не делает весь Promise.allSettled() отклонённым
Это ключевое отличие от Promise.all().
Promise.allSettled([
Promise.resolve("ok"),
Promise.reject(new Error("boom")),
Promise.resolve("done"),
])
.then((results) => {
console.log(results);
})
.catch((error) => {
console.log("Не выполнится", error);
});
Здесь catch() из-за обычной ошибки одного элемента не нужен, потому что Promise.allSettled() всё равно вернёт массив результатов.
Как читать результат Promise.allSettled()
Это особенно полезная часть в реальном коде.
Сначала обычно проверяют status, а потом уже читают value или reason.
Promise.allSettled([
Promise.resolve(1),
Promise.reject(new Error("fail")),
Promise.resolve(3),
]).then((results) => {
for (const item of results) {
if (item.status === "fulfilled") {
console.log("Успех:", item.value);
} else {
console.log("Ошибка:", item.reason);
}
}
});
Такой подход безопаснее, чем пытаться читать value у каждого элемента подряд.
Как отделить успешные результаты от ошибок
Это один из самых частых практических сценариев.
Promise.allSettled([
Promise.resolve(1),
Promise.reject(new Error("fail")),
Promise.resolve(3),
]).then((results) => {
const successValues = results
.filter((item) => item.status === "fulfilled")
.map((item) => item.value);
const errors = results
.filter((item) => item.status === "rejected")
.map((item) => item.reason);
console.log(successValues); // [1, 3]
console.log(errors); // [Error("fail")]
});
Это особенно удобно, когда часть результатов всё равно можно использовать, даже если остальные завершились с ошибкой.
Пустой массив даёт успешный результат []
Это полезно помнить.
Promise.allSettled([]).then((results) => {
console.log(results); // []
});
Если передать пустой массив, результатом будет успешно завершённый промис с пустым массивом.
При этом обработчик then() всё равно выполнится асинхронно:
console.log("start");
Promise.allSettled([]).then((results) => {
console.log(results); // []
});
console.log("end");
Результат будет таким:
start
end
[]
Чем Promise.allSettled() отличается от Promise.all()
Это сравнение стоит запомнить.
Promise.all()подходит, когда нужен полный успех всех элементовPromise.allSettled()подходит, когда нужно дождаться вообще всех результатов, включая ошибки
Promise.all([
Promise.resolve("ok"),
Promise.reject(new Error("boom")),
]).catch((error) => {
console.log("all:", error.message); // "boom"
});
Promise.allSettled([
Promise.resolve("ok"),
Promise.reject(new Error("boom")),
]).then((results) => {
console.log("allSettled:", results);
});
Если ошибка одной операции не должна ломать весь сбор результатов, обычно удобнее именно Promise.allSettled().
Когда Promise.allSettled() всё же может завершиться с ошибкой
Это более редкий, но полезный нюанс.
Если проблема возникает не в самих промисах, а в переданном аргументе, итоговый промис может стать rejected.
Например:
Promise.allSettled(123).catch((error) => {
console.log(error.name); // "TypeError"
});
Потому что метод ожидает итерируемый объект, а число им не является.
Когда это полезно
Promise.allSettled() особенно удобен, когда:
- нужно получить результаты всех операций независимо от ошибок
- часть данных можно использовать даже при частичном падении
- вы хотите собрать успешные ответы и ошибки отдельно
- важно показать пользователю полную картину, а не остановиться на первой ошибке
Пример:
Promise.allSettled([
fetch("/api/user").then((response) => response.json()),
fetch("/api/settings").then((response) => response.json()),
fetch("/api/notifications").then((response) => response.json()),
]).then((results) => {
console.log(results);
});
Такой подход особенно удобен, когда запросы независимы и неудача одного из них не должна скрывать остальные результаты.
Частые ошибки
Ожидать, что Promise.allSettled() упадёт на первой ошибке
Promise.allSettled([
Promise.resolve("ok"),
Promise.reject(new Error("boom")),
]).then((results) => {
console.log(results);
});
Обычная ошибка одного элемента не делает итоговый промис отклонённым.
Пытаться читать value у каждого элемента без проверки status
Promise.allSettled([
Promise.resolve(1),
Promise.reject("x"),
]).then((results) => {
console.log(results[1].value); // undefined
});
Сначала нужно смотреть на status, а уже потом читать value или reason.
Думать, что результаты приходят в порядке завершения
const first = new Promise((resolve) => {
setTimeout(() => resolve("first"), 50);
});
const second = new Promise((resolve) => {
setTimeout(() => resolve("second"), 10);
});
Promise.allSettled([first, second]).then((results) => {
console.log(results[0].value); // "first"
console.log(results[1].value); // "second"
});
Порядок зависит от входного массива, а не от скорости выполнения.
Думать, что обычные значения внутри массива недопустимы
Promise.allSettled([1, Promise.resolve(2)]).then((results) => {
console.log(results);
});
Обычные значения допустимы и становятся элементами со статусом "fulfilled".
Передавать неитерируемое значение
Promise.allSettled(123).catch((error) => {
console.log(error.name); // "TypeError"
});
Метод ожидает массив или другой итерируемый объект.
Быстрая памятка
Promise.allSettled()вызывается уPromise- метод всегда возвращает объект
Promise - результатом обычно будет массив объектов со статусом
- формат элемента:
{ status: "fulfilled", value: ... }или{ status: "rejected", reason: ... } - порядок результата совпадает с порядком входных элементов
- обычные значения внутри массива допустимы
- метод ждёт завершения всех элементов
- ошибка одного элемента не ломает весь результат
- пустой массив даёт успешный результат
[] - перед чтением
valueилиreasonнужно проверятьstatus
Коротко
Promise.allSettled() в JavaScript нужен, чтобы дождаться завершения всех промисов и получить по каждому из них отдельный итог. Главное, что стоит запомнить: метод не падает из-за обычной ошибки одного элемента, возвращает массив объектов со статусами, сохраняет порядок входных значений и особенно полезен тогда, когда нужно собрать вместе и успешные результаты, и ошибки.