Каким методом промиса выполнить несколько параллельных запросов и получить результат каждого
Что проверяют
Для Android-разработчика вопрос про JavaScript обычно значит React Native, WebView с мостом в нативный код или проверку кругозора в асинхронности. Интервьюер хочет услышать разницу между Promise.all и Promise.allSettled и понять, переносите ли вы её на корутины. Следом почти всегда спрашивают, что будет, если один запрос упадёт.
Как отвечать
Точный ответ на «результат каждого» это Promise.allSettled, но начинать стоит с Promise.all:
Promise.all(promises): ждёт все промисы и отдаёт массив результатов в том же порядке, в каком их передали, независимо от того, кто ответил первым. Если хотя бы один отклонён, общий промис сразу отклоняется этой ошибкой, и успешные результаты теряются;Promise.allSettled(promises)(ES2020): ждёт завершения всех и никогда не отклоняется. По каждому элементу приходит{ status: "fulfilled", value }или{ status: "rejected", reason }, и вы сами решаете, что делать с упавшими.
Параллельность дают не эти методы, а момент создания промисов: запрос стартует при вызове fetch, а Promise.all только ждёт. Поэтому await в цикле for выполняет запросы по очереди, а urls.map((url) => fetch(url)) с последующим Promise.all запускает их одновременно.
Сильный ход провести параллель с Kotlin. coroutineScope { ids.map { async { api.load(it) } }.awaitAll() } ведёт себя как Promise.all, только при ошибке одного запроса остальные корутины отменяются. Аналог allSettled: ловить ошибку внутри каждого async и собирать список Result, не забывая пробрасывать CancellationException, которую runCatching тоже перехватывает.
Где спотыкаются
Думают, что Promise.all при ошибке отменяет остальные запросы. Промисы не отменяются: запросы доходят до сервера, их результаты просто игнорируются. Отменять нужно явно, через AbortController.
Путают порядок и считают, что результаты приходят в порядке завершения. Порядок всегда совпадает с порядком входного массива.
Пишут await внутри цикла и называют это параллельными запросами. Время ответа складывается из всех запросов, а не равно самому медленному.