Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Что такое Promise.allSettled?
Promise.allSettled() — это статический метод объекта Promise в JavaScript, который принимает итерируемую коллекцию промисов (чаще всего массив) и возвращает единственный промис, который разрешается только после того, как все переданные промисы завершатся (неважно — успешно или с ошибкой). В отличие от Promise.all(), который немедленно отклоняется при первой же ошибке, allSettled ждет завершения всех промисов и предоставляет информацию о результате каждого из них в виде массива объектов с детализированным статусом.
Основная концепция
Метод Promise.allSettled() появился в спецификации ES2020 и решает важную проблему: необходимость знать окончательный результат всех асинхронных операций, даже если некоторые из них завершились неудачно. Это особенно полезно в сценариях, где несколько независимых задач должны быть выполнены полностью, и вам нужно обработать как успешные, так и неудачные результаты.
Синтаксис
Promise.allSettled(iterable);
- iterable — итерируемый объект (обычно массив), содержащий промисы или другие значения
- Возвращает: промис, который разрешается с массивом объектов результатов
Структура результатов
Каждый элемент в результирующем массиве имеет следующую структуру:
// Для успешно выполненных промисов
{
status: "fulfilled",
value: результат_промиса
}
// Для отклоненных промисов
{
status: "rejected",
reason: ошибка_промиса
}
Примеры использования
Базовый пример
const promise1 = Promise.resolve(42);
const promise2 = Promise.reject("Ошибка в promise2");
const promise3 = new Promise((resolve) => setTimeout(() => resolve(100), 100));
Promise.allSettled([promise1, promise2, promise3])
.then((results) => {
results.forEach((result, index) => {
console.log(`Промис ${index}:`, result);
});
});
// Результат:
// Промис 0: {status: "fulfilled", value: 42}
// Промис 1: {status: "rejected", reason: "Ошибка в promise2"}
// Промис 2: {status: "fulfilled", value: 100}
Практический пример с запросами к API
const apiUrls = [
'/api/user/1',
'/api/user/2',
'/api/user/999', // несуществующий пользователь
'/api/user/4'
];
// Преобразуем URL в промисы запросов
const fetchPromises = apiUrls.map(url =>
fetch(url)
.then(response => {
if (!response.ok) throw new Error(`HTTP error: ${response.status}`);
return response.json();
})
.catch(error => Promise.reject(error))
);
Promise.allSettled(fetchPromises)
.then(results => {
const successfulResults = [];
const failedResults = [];
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
successfulResults.push({
url: apiUrls[index],
data: result.value
});
} else {
failedResults.push({
url: apiUrls[index],
error: result.reason.message
});
}
});
console.log('Успешные запросы:', successfulResults.length);
console.log('Неудачные запросы:', failedResults.length);
console.log('Все результаты обработаны!');
// Можно продолжить обработку успешных результатов
processSuccessfulData(successfulResults);
});
Сравнение с другими методами Promise
Promise.allSettled() vs Promise.all()
| Аспект | Promise.all() | Promise.allSettled() |
|---|---|---|
| Поведение при ошибке | Немедленно отклоняется при первой ошибке | Ожидает завершения всех промисов |
| Результат при успехе | Массив значений разрешенных промисов | Массив объектов с детализацией статуса |
| Результат при ошибке | Одна ошибка (первая) | Все равно массив объектов с результатами всех промисов |
| Использование | Когда все промисы должны успешно выполниться | Когда нужны результаты всех операций независимо от успеха |
Promise.allSettled() vs Promise.any() vs Promise.race()
// Разные стратегии обработки нескольких промисов:
// 1. allSettled - ждем ВСЕ результаты
Promise.allSettled([promise1, promise2]).then(allResults => {});
// 2. race - первый завершенный (успешно или с ошибкой)
Promise.race([promise1, promise2]).then(firstResult => {});
// 3. any - первый УСПЕШНЫЙ результат (игнорирует ошибки)
Promise.any([promise1, promise2]).then(firstSuccessful => {});
Полифил для старых браузеров
Для поддержки в старых окружениях можно использовать полифил:
if (!Promise.allSettled) {
Promise.allSettled = function(promises) {
return Promise.all(
promises.map(promise =>
Promise.resolve(promise).then(
value => ({
status: 'fulfilled',
value
}),
reason => ({
status: 'rejected',
reason
})
)
)
);
};
}
Практические сценарии применения
Promise.allSettled() особенно полезен в следующих ситуациях:
-
Загрузка данных из нескольких независимых источников
- Когда нужно загрузить данные из нескольких API одновременно
- Важно обработать все ответы, даже если некоторые запросы завершились ошибкой
-
Параллельное выполнение независимых задач
- Обработка нескольких файлов или изображений
- Отправка данных в разные системы логирования или аналитики
-
Сбор метрик и диагностика
- Когда нужно собрать информацию о выполнении различных операций
- Для составления полного отчета о работе системы
-
Чистка ресурсов или откат изменений
- При необходимости отменить несколько операций независимо от их успеха
Обработка результатов
Фильтрация успешных результатов
Promise.allSettled(promisesArray)
.then(results => {
// Получаем только успешные результаты
const successful = results
.filter(result => result.status === 'fulfilled')
.map(result => result.value);
// Получаем только ошибки с дополнительной информацией
const errors = results
.filter(result => result.status === 'rejected')
.map(result => result.reason);
return { successful, errors };
});
Последовательная обработка с сохранением структуры
async function processMultipleRequests(urls) {
const results = await Promise.allSettled(
urls.map(url => fetchData(url))
);
// Сохраняем исходный порядок и структуру
return results.map((result, index) => ({
url: urls[index],
status: result.status,
data: result.status === 'fulfilled' ? result.value : null,
error: result.status === 'rejected' ? result.reason : null
}));
}
Важные особенности
- Не-промисы автоматически оборачиваются в
Promise.resolve() - Порядок результатов сохраняется согласно порядку исходных промисов
- Не вызывает
unhandledrejectionдля отклоненных промисов, так как все они обрабатываются - Работает с любым итерируемым объектом, не только с массивами
Заключение
Promise.allSettled() — это мощный инструмент для работы с несколькими асинхронными операциями, когда важно получить информацию о результате всех операций, а не только об успешных. Он предоставляет детализированную информацию о состоянии каждого промиса, что позволяет создавать более устойчивые и информативные системы обработки асинхронных операций в JavaScript. Этот метод стал стандартным выбором для сценариев, где требуется параллельное выполнение независимых задач с полным контролем над результатами каждой из них.