Promise.allSettled: как сохранить частичные результаты запросов

Promise.allSettled: как сохранить частичные результаты запросов
Содержание статьи

Promise.allSettled подходит, когда независимые операции могут завершиться по-разному, а интерфейсу нужны и успешные результаты, и сведения об ошибках. Он ждёт завершения всех переданных промисов и возвращает массив исходов. На Mentoring.digital разберём такой сценарий без настоящих сетевых запросов.

Сначала решите, допустим ли частичный ответ

Для независимых карточек отчёта частичный результат иногда полезнее пустого экрана. Для зависимой последовательности, где второй шаг нельзя выполнять без первого, один allSettled не создаёт правильную бизнес-логику. Выбор начинается с вопроса: что пользователь сможет безопасно сделать, если одна часть отсутствует?

Promise.all отклоняет общий промис при отклонении одного из входных. allSettled сохраняет отдельный status для каждого. Это не означает автоматической отмены, повторной попытки или ограничения числа одновременно работающих операций.

Сопоставляйте исходы с исходным списком

async function example() {
  const jobs = [
    {id: "profile", run: () => Promise.resolve({name: "Demo"})},
    {id: "history", run: () => Promise.reject(new Error("Unavailable"))},
  ];
  const results = await Promise.allSettled(
    jobs.map(job => Promise.resolve().then(job.run))
  );
  return results.map((result, index) => ({
    id: jobs[index].id,
    ok: result.status === "fulfilled",
    ...(result.status === "fulfilled"
      ? {data: result.value}
      : {error: "Раздел временно недоступен"}),
  }));
}

example().then(console.log);

Порядок массива исходов соответствует порядку входных промисов, а не скорости завершения. Поэтому index позволяет вернуть ID нужной задачи. Обёртка через then превращает и синхронное исключение job.run в отклонение промиса. Ветвление по status предшествует обращению к value.

Не превращайте ошибку в пустой успех

Пустой массив и недоступный раздел означают разное. В интерфейсе сохраните явное состояние ошибки, а в диагностике используйте безопасный идентификатор операции. Не показывайте пользователю сырое reason: там могут оказаться внутренние адреса или детали запроса.

При замене примера на fetch отдельно обработайте HTTP-статус: ответ 500 сам по себе не заставляет fetch отклонить промис. Функция загрузки должна проверять response.ok и формировать согласованную ошибку. allSettled классифицирует исход промиса, а не смысл ответа сервера.

Что проверить тестом

  • Все задачи успешны.
  • Одна или все задачи отклонены.
  • Завершение происходит в другом порядке.
  • Функция задачи выбрасывает исключение до возврата промиса.
  • Пустой список и операция, которая не завершается.

Для последнего случая нужен отдельно спроектированный предел ожидания или отмена в самом клиенте. Схему частичных ответов и отображение состояний можно обсудить с наставником по JavaScript. Успешное завершение allSettled не означает, что успешны все задачи.

Похожие статьи по данной теме