← Назад к вопросам

Что такое Promise.allSettled?

1.0 Junior🔥 211 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Что такое 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() особенно полезен в следующих ситуациях:

  1. Загрузка данных из нескольких независимых источников

    • Когда нужно загрузить данные из нескольких API одновременно
    • Важно обработать все ответы, даже если некоторые запросы завершились ошибкой
  2. Параллельное выполнение независимых задач

    • Обработка нескольких файлов или изображений
    • Отправка данных в разные системы логирования или аналитики
  3. Сбор метрик и диагностика

    • Когда нужно собрать информацию о выполнении различных операций
    • Для составления полного отчета о работе системы
  4. Чистка ресурсов или откат изменений

    • При необходимости отменить несколько операций независимо от их успеха

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

Фильтрация успешных результатов

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
  }));
}

Важные особенности

  1. Не-промисы автоматически оборачиваются в Promise.resolve()
  2. Порядок результатов сохраняется согласно порядку исходных промисов
  3. Не вызывает unhandledrejection для отклоненных промисов, так как все они обрабатываются
  4. Работает с любым итерируемым объектом, не только с массивами

Заключение

Promise.allSettled() — это мощный инструмент для работы с несколькими асинхронными операциями, когда важно получить информацию о результате всех операций, а не только об успешных. Он предоставляет детализированную информацию о состоянии каждого промиса, что позволяет создавать более устойчивые и информативные системы обработки асинхронных операций в JavaScript. Этот метод стал стандартным выбором для сценариев, где требуется параллельное выполнение независимых задач с полным контролем над результатами каждой из них.