В чем разница между Promise.all и Promise.allSettled в JavaScript?
Что проверяют
Знаете ли вы поведение при отказе и понимаете ли, что проигравшие промисы не отменяются.
Как отвечать
Promise.all ждёт все промисы и возвращает массив их значений в порядке аргументов, а не в порядке завершения. Но при первом же отказе он немедленно отклоняется этой ошибкой, и все успешные результаты теряются. Это поведение «всё или ничего».
Promise.allSettled тоже ждёт все, но никогда не отклоняется. Возвращает массив объектов вида { status: "fulfilled", value } или { status: "rejected", reason }, по одному на каждый входной промис.
const [a, b] = await Promise.all([loadUser(), loadJobs()]); // упало одно, нет ничего
const res = await Promise.allSettled([loadWidget1(), loadWidget2()]);
res.filter((r) => r.status === "fulfilled").forEach(render); // рисуем то, что пришлоКогда что:
allкогда все части обязательны: без любой из них страницу всё равно не показать. Быстрый отказ тут даже полезен, не надо ждать остальные;allSettledкогда допустим частичный успех: панель из трёх виджетов, один источник недоступен, остальные показываем. Также для параллельных фоновых операций, где важно знать итог каждой.
Важная общая деталь: отказ или победа не отменяют остальные промисы. Они продолжают выполняться, их запросы уходят на сервер, просто результат игнорируется. Для настоящей отмены нужен AbortController.
И вторая: промис начинает выполняться в момент создания, а не в момент передачи в all. Поэтому передавать надо уже созданные промисы, а если нужно ограничить одновременность, оборачивать в функции и запускать порциями.
Рядом стоят Promise.any (первый успешный, иначе AggregateError) и Promise.race (первый завершившийся любым способом).
Где спотыкаются
Ждут, что all вернёт частичный результат при ошибке.
Используют all там, где нужен allSettled, и теряют всё из-за одного сбоя.
Считают, что отказ отменяет остальные запросы.
Забывают, что порядок результатов соответствует аргументам, а не скорости ответа.