> Каким методом промиса получить результат первого выполненного запроса (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: SmartWay
Стек: JavaScript
> Пример ответа
Короткий ответ
Для получения результата первого выполненного запроса используется статический метод Promise.race(). Он принимает итератор промисов и возвращает новый промис, который разрешается или отклоняется значением первого завершившегося (settled) промиса. Важно: если первый завершившийся промис будет rejected, то Promise.race() тоже завершится с ошибкой, игнорируя успешные результаты остальных.
Подробное объяснение
Promise.race() - один из статических методов Promise API. Его суть: из переданного списка промисов возвращается результат того, который завершится первым (как resolve, так и reject). Это поведение отличается от Promise.any(), который ждёт первого успешного (fulfilled) результата, игнорируя reject до первого resolve.
Механизм работы:
- Все промисы запускаются параллельно
- Как только любой из них переходит в состояние settled (fulfilled или rejected),
Promise.race()немедленно завершается с тем же результатом - Остальные промисы продолжают выполняться, но их результаты игнорируются
Этот метод полезен для:
- Таймаутов: комбинируем запрос с промисом, который отклоняется через заданное время
- Гонки запросов к разным источникам данных (например, CDN)
- Получения самого быстрого ответа от нескольких серверов
На практике
В реальных проектах Promise.race() часто используют для реализации таймаутов:
JAVASCRIPTconst fetchWithTimeout = (url, timeout = 5000) => {const controller = new AbortController();const timeoutPromise = new Promise((_, reject) => {setTimeout(() => {controller.abort();reject(new Error('Request timed out'));}, timeout);});return Promise.race([fetch(url, { signal: controller.signal }),timeoutPromise]);};
Также применяется для выбора самого быстрого источника данных:
JAVASCRIPTconst getFastestResponse = async (urls) => {const promises = urls.map(url => fetch(url).then(r => r.json()));return Promise.race(promises);};
Пример кода
JAVASCRIPT// Пример с разным временем выполненияconst slowPromise = new Promise(resolve =>setTimeout(() => resolve('медленный'), 3000));const fastPromise = new Promise(resolve =>setTimeout(() => resolve('быстрый'), 1000));Promise.race([slowPromise, fastPromise]).then(result => console.log(result)); // 'быстрый'// Пример с ошибкойconst errorPromise = Promise.reject(new Error('ошибка'));const successPromise = Promise.resolve('успех');Promise.race([errorPromise, successPromise]).then(result => console.log(result)).catch(err => console.error(err.message)); // 'ошибка'
Как отвечать на собеседовании
Начни с чёткого определения: Promise.race() возвращает результат первого завершившегося промиса, независимо от его статуса. Подчеркни разницу с Promise.any() (первый успешный) и Promise.allSettled() (все результаты). Приведи реальный кейс - таймаут для fetch. Упомяни, что остальные промисы не отменяются, а продолжают выполняться в фоне, что может быть проблемой для производительности. Если собеседник спросит про альтернативы, скажи, что для отмены запросов лучше использовать AbortController в комбинации с Promise.race().
Что проверяет интервьюер
- Понимание различий между
race,any,allиallSettled - Знание edge cases: что будет, если первый промис rejected
- Умение применять метод в реальных сценариях (таймауты, fallback-запросы)
- Понимание асинхронного выполнения и event loop (промисы не отменяются)
- Способность объяснить trade-off: скорость vs надёжность
Типичные ошибки
- Путают
Promise.race()сPromise.any()- первый берёт любой результат, второй только успешный - Думают, что
Promise.race()отменяет остальные промисы - это не так, они продолжают выполняться - Используют
Promise.race()для гонки запросов без обработки ошибок - если первый запрос упадёт, весь промис упадёт - Забывают, что в
Promise.race()можно передать пустой массив - тогда промис зависнет навсегда (pending) - Не учитывают, что результат приходит только от первого завершившегося, а не от самого быстрого успешного
> Похожие задачи по frontend
Как работают редьюсеры в Redux
Как отслеживать события мыши на canvas во frontend
Какие инструменты позволяют убрать нагрузку с основного потока в JavaScript
Как работает Google Maps на стороне frontend
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью