> В чем разница между Promise.all, Promise.any и Promise.race в JavaScript (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: IT-One, EPAM, Яндекс
Стек: JavaScript
> Пример ответа
Короткий ответ
Promise.all завершается успешно, когда все промисы разрешены, или сразу отклоняется при первом rejection. Promise.race завершается результатом первого завершившегося промиса (любого статуса). Promise.any завершается успешно при первом fulfilled, а отклоняется только если все промисы отклонены. Разница в стратегии обработки множества асинхронных операций.
Подробное объяснение
Все три метода принимают iterable промисов и возвращают новый промис, но ведут себя принципиально различно:
-
Promise.all: ожидает выполнения всех промисов. Если хотя бы один отклоняется, весь
Promise.allнемедленно отклоняется с ошибкой первого rejection. Успешный результат - массив значений в том же порядке, что и исходные промисы. Используется, когда все операции обязательны для дальнейшей работы. -
Promise.race: возвращает результат первого завершившегося промиса - неважно, resolve или reject. Если первый завершившийся промис отклоняется,
Promise.raceотклоняется. Подходит для таймаутов или гонки между несколькими источниками данных. -
Promise.any: возвращает первый успешно разрешённый промис. Если все промисы отклонены, возвращает
AggregateError(массив ошибок). Игнорирует rejection, пока есть хотя бы один успешный. Полезен, когда нужно получить первый успешный ответ из нескольких независимых источников.
Ключевое отличие - Promise.all и Promise.race чувствительны к первому rejection, а Promise.any - нет.
На практике
Promise.all- загрузка данных с нескольких эндпоинтов, где каждый обязателен для отображения страницы. Если один запрос падает, показывать частичные данные бессмысленно.Promise.race- установка таймаута для запроса:Promise.race([fetch(url), timeout(5000)]). Если таймаут срабатывает раньше, запрос отменяется.Promise.any- получение данных из нескольких CDN или API-провайдеров. Достаточно первого успешного ответа, остальные игнорируются.
Важно помнить, что Promise.any не отменяет остальные промисы - они продолжают выполняться, но их результаты игнорируются.
Пример кода
JAVASCRIPTconst p1 = Promise.resolve(1);const p2 = Promise.reject(new Error('ошибка'));const p3 = new Promise(resolve => setTimeout(() => resolve(3), 100));// Promise.all - отклоняется при первом rejectionPromise.all([p1, p2, p3]).then(console.log) // не выполнится.catch(err => console.log('all rejected:', err.message)); // "ошибка"// Promise.race - первый завершившийся (p2)Promise.race([p1, p2, p3]).then(console.log) // не выполнится.catch(err => console.log('race rejected:', err.message)); // "ошибка"// Promise.any - первый успешный (p1)Promise.any([p1, p2, p3]).then(result => console.log('any resolved:', result)) // 1.catch(err => console.log('any rejected:', err.errors));
Как отвечать на собеседовании
Начни с краткого определения каждого метода, затем перейди к сравнению их поведения при rejection. Приведи практические примеры использования для каждого случая. Упомяни, что Promise.any появился в ES2021 и может требовать полифилла. Покажи понимание, что эти методы не отменяют промисы - они лишь агрегируют результаты. Хорошо упомянуть Promise.allSettled как четвёртый вариант, который ждёт все промисы независимо от статуса.
Что проверяет интервьюер
- Понимание асинхронного управления в JavaScript
- Умение выбирать правильный инструмент под конкретную задачу
- Знание нюансов поведения при rejection
- Осведомлённость о современных возможностях (Promise.any)
- Понимание, что промисы неотменяемы
Типичные ошибки
- Путать
Promise.raceиPromise.any: первый реагирует на любой завершившийся промис, второй - только на успешный - Думать, что
Promise.allвозвращает результаты в порядке завершения - на самом деле порядок соответствует исходному массиву - Предполагать, что
Promise.anyотменяет остальные промисы - они продолжают выполняться - Забывать про
AggregateErrorвPromise.anyпри всех rejection - Использовать
Promise.allтам, где достаточноPromise.any(например, при дублировании запросов)
> Похожие задачи по frontend
Можно ли изменять массивы и объекты, объявленные через const в JavaScript?
Каков порядок выполнения задач (task) и микротасков (microtask) в JavaScript
Почему стрелочную функцию нельзя использовать как конструктор в JavaScript
Как реализовать функцию any, которая работает как Promise.any?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью