Комбинаторы промисов

Четыре статических метода для работы с группой промисов: all, race, allSettled, any — и когда каждый из них.

Комбинаторы промисов принимают массив промисов и возвращают один общий промис, который завершается по своей логике объединения.

Promise.all — все или ничего

Promise.all ждёт, пока выполнятся все промисы, и отдаёт массив результатов в исходном порядке. Если хотя бы один отклонится — общий промис немедленно отклоняется с этой ошибкой:

const p1 = Promise.resolve(1);
const p2 = new Promise(r => setTimeout(() => r(2), 10));
const p3 = Promise.resolve(3);

Promise.all([p1, p2, p3]).then(values => console.log("all:", values.join(", ")));

Вывод:

all: 1, 2, 3

Порядок результатов соответствует порядку в массиве, а не порядку завершения. Теперь — поведение при ошибке:

const ok = Promise.resolve("ok");
const bad = Promise.reject(new Error("упал"));

Promise.all([ok, bad])
  .then(v => console.log("успех:", v))
  .catch(e => console.log("all отклонился:", e.message));

Вывод:

all отклонился: упал

Promise.race — кто первый

Promise.race завершается, как только завершится первый промис — неважно, успехом или ошибкой. Удобно для таймаутов:

const slow = new Promise(r => setTimeout(() => r("медленный"), 50));
const fast = new Promise(r => setTimeout(() => r("быстрый"), 10));

Promise.race([slow, fast]).then(v => console.log("race победитель:", v));

Вывод:

race победитель: быстрый

Promise.allSettled — ждём всех, ошибки не страшны

Promise.allSettled дожидается завершения всех промисов и никогда не отклоняется. Возвращает массив объектов { status, value } или { status, reason }. Идеально, когда нужно собрать все результаты, даже если часть упала:

const tasks = [
  Promise.resolve("A ок"),
  Promise.reject(new Error("B упал")),
  Promise.resolve("C ок")
];

Promise.allSettled(tasks).then(results => {
  for (const r of results) {
    if (r.status === "fulfilled") console.log("успех:", r.value);
    else console.log("ошибка:", r.reason.message);
  }
});

Вывод:

успех: A ок
ошибка: B упал
успех: C ок

Promise.any — первый успех

Promise.any отдаёт результат первого успешного промиса, игнорируя ошибки. Отклоняется только если упали все (с AggregateError):

const tasks = [
  Promise.reject(new Error("первый упал")),
  new Promise(r => setTimeout(() => r("второй ок"), 10)),
  Promise.reject(new Error("третий упал"))
];

Promise.any(tasks).then(v => console.log("any:", v));

Вывод:

any: второй ок

Шпаргалка: когда что

МетодКогда завершаетсяПрименение
allвсе успешны / первый упалнужны ВСЕ результаты, любой сбой критичен
raceпервый любой результаттаймауты, «кто быстрее»
allSettledвсе завершилисьсобрать отчёт, ошибки не критичны
anyпервый успех / все упалинесколько источников, хватит одного

Итог

  • all — «все или ничего», порядок результатов сохраняется.
  • race и any ловят первого: первый любой против первого успешного.
  • allSettled никогда не падает — даёт полный отчёт по каждому.
Проверьте себя
1. Что вернёт Promise.all, если один из промисов отклонится?
AМассив с undefined вместо упавшего
BНемедленно отклонится с этой ошибкой
CДождётся остальных и вернёт частичный массив
DПроигнорирует ошибку
2. Какой комбинатор никогда не отклоняется и даёт статус по каждому промису?
APromise.all
BPromise.race
CPromise.allSettled
DPromise.any
3. Что делает Promise.any?
AЖдёт первый любой результат
BВозвращает первый успешный, игнорируя ошибки
CЖдёт все промисы
DВсегда отклоняется при первой ошибке
4. Для реализации таймаута («что быстрее») лучше всего подходит:
APromise.all
BPromise.race
CPromise.allSettled
DPromise.any
Поддержать проект