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

Как узнать при выполнении нескольких Promise какие упали и какие выполнились?

2.3 Middle🔥 261 комментариев
#JavaScript Core

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

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

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

Обработка нескольких Promise и анализ их статусов

При работе с несколькими асинхронными операциями, которые представлены объектами Promise, возникает необходимость отслеживать их состояние выполнения. Для решения этой задачи в JavaScript существуют несколько подходов, каждый из которых подходит для разных сценариев.

Метод Promise.allSettled()

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

const promise1 = Promise.resolve('Успех 1');
const promise2 = Promise.reject(new Error('Ошибка 2'));
const promise3 = Promise.resolve('Успех 3');

Promise.allSettled([promise1, promise2, promise3])
  .then((results) => {
    results.forEach((result, index) => {
      console.log(`Промис ${index + 1}:`, {
        статус: result.status,
        значение: result.value,
        причина: result.reason
      });
      
      if (result.status === 'fulfilled') {
        console.log(`✓ Промис ${index + 1} выполнился:`, result.value);
      } else {
        console.log(`✗ Промис ${index + 1} упал:`, result.reason);
      }
    });
  });

Каждый элемент в массиве результатов имеет структуру:

  • status — строка 'fulfilled' или 'rejected'
  • value — значение выполненных промисов (только при status: 'fulfilled')
  • reason — причина отказа (только при status: 'rejected')

Альтернативные подходы

1. Обработка каждого промиса индивидуально

Можно обернуть каждый промис в обработку, которая сохраняет информацию о его статусе:

const promises = [
  Promise.resolve('data1'),
  Promise.reject('error2'),
  Promise.resolve('data3')
];

const statuses = [];

promises.forEach((promise, index) => {
  promise
    .then(result => {
      statuses[index] = { status: 'fulfilled', value: result };
    })
    .catch(error => {
      statuses[index] = { status: 'rejected', reason: error };
    });
});

// Проверяем статусы после завершения всех промисов
Promise.allSettled(promises).then(() => {
  console.log('Все статусы:', statuses);
});

2. Использование Promise.all() с обработкой ошибок

Promise.all() останавливается при первой ошибке, но можно модифицировать подход:

const promises = [
  Promise.resolve('data1'),
  Promise.reject('error2'),
  Promise.resolve('data3')
];

const wrappedPromises = promises.map(p => 
  p.then(
    value => ({ status: 'fulfilled', value }),
    reason => ({ status: 'rejected', reason })
  )
);

Promise.all(wrappedPromises)
  .then(results => {
    results.forEach((result, index) => {
      console.log(`Промис ${index}:`, result);
    });
  });

Сравнение методов

МетодПреимуществаНедостатки
Promise.allSettled()Специально создан для этой задачи, чистый API, стандартный подходПоддерживается не в очень старых браузерах
Индивидуальная обработкаПолный контроль над каждым промисомБолее многословный код
Promise.all() с оберткойРаботает в старых средахТребует дополнительной обертки

Практические рекомендации

  1. Для современных приложений всегда предпочитайте Promise.allSettled() — это наиболее выразительный и понятный способ.
  2. Если важна производительность при большом количестве промисов, Promise.allSettled() обычно оптимален.
  3. Для совместимости со старыми браузерами используйте полифил или подход с оберткой промисов.
  4. При отладке можно добавить идентификаторы к промисам для более простого отслеживания:
const createTrackablePromise = (promise, id) => {
  return promise
    .then(value => ({ id, status: 'fulfilled', value }))
    .catch(error => ({ id, status: 'rejected', error }));
};

Пример полного решения с анализом

async function analyzePromises(promiseArray) {
  const results = await Promise.allSettled(promiseArray);
  
  const analysis = {
    fulfilled: results.filter(r => r.status === 'fulfilled'),
    rejected: results.filter(r => r.status === 'rejected'),
    total: results.length,
    successRate: (results.filter(r => r.status === 'fulfilled').length / results.length) * 100
  };
  
  console.log('Анализ выполнения промисов:');
  console.log(`Успешно: ${analysis.fulfilled.length}`);
  console.log(`С ошибками: ${analysis.rejected.length}`);
  console.log(`Процент успеха: ${analysis.successRate.toFixed(2)}%`);
  
  return analysis;
}

Ключевой вывод: Современный JavaScript предоставляет инструменты, которые делают анализ выполнения нескольких промисов простым и предсказуемым. Выбор метода зависит от требований к совместимости и конкретного случая использования, но Promise.allSettled() должен быть вашим первым выбором для новых проектов.