Каким методом промиса выполнить несколько параллельных запросов и получить результат каждого
Что проверяют
Интервьюер ждёт не только название метода, но и разницу между Promise.all и Promise.allSettled, а ещё то, как вы переживёте частичный отказ на реальной странице. Следом обычно спрашивают, как ограничить число одновременных запросов или отменить их при уходе со страницы.
Как отвечать
Promise.all: массив результатов в порядке входного массива, но при первом отклонении отклоняется весь промис. Подходит, когда без любого из ответов экран бессмыслен, например профиль и права доступа;Promise.allSettled: дожидается всех и по каждому отдаёт{ status, value }или{ status, reason }. Подходит для дашборда из независимых виджетов: упал один, остальные показываем.
const controller = new AbortController();
const results = await Promise.allSettled(
urls.map((url) => fetch(url, { signal: controller.signal }).then((r) => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
}))
);Детали, которые отличают сильный ответ:
fetchне отклоняет промис на 404 или 500, только на сетевую ошибку или отмену, поэтомуr.okпроверяют вручную;- запросы стартуют в момент вызова
fetch, аPromise.allих только ждёт.awaitв циклеforпревращает параллельные запросы в очередь; - отмена через
AbortController: одинsignalна все запросы иcontroller.abort()в функции очисткиuseEffect; - сотни запросов разом запускать плохо: по HTTP/1.1 браузер держит около шести соединений на хост, остальные ждут в очереди. Ограничивайте пул, например через
p-limit, или просите у бэкенда пакетный эндпоинт.
Где спотыкаются
Забывают, что fetch не падает на 404: Promise.all завершается успешно, а дальше код разбирает тело ответа с ошибкой как обычные данные.
Считают, что Promise.all отменяет остальные запросы после первой ошибки. Они продолжают выполняться, а их результаты уходят в пустоту.
Берут allSettled, но не проверяют status и читают value у каждого элемента. У отклонённых там undefined, и ошибка просто переезжает в рендер.