> Каким методом промиса получить результат первого выполненного запроса (JavaScript)

Уровень: senior · Роль: qa · Категория: Технические вопросы

Компании: Автомакон

Стек: JavaScript

> Пример ответа

Короткий ответ

Для получения результата первого выполненного промиса используется статический метод Promise.race(). Он принимает итерируемую коллекцию промисов (обычно массив) и возвращает новый промис, который разрешается значением первого завершившегося (как успешно, так и с ошибкой) промиса из переданной коллекции.

Подробное объяснение

Promise.race() - один из статических методов работы с промисами в JavaScript. Его ключевая особенность: он реагирует на самый быстрый промис, независимо от того, завершился он успешно (resolve) или с ошибкой (reject). Если первый завершившийся промис переходит в состояние fulfilled, то Promise.race() возвращает его значение. Если первый завершившийся промис переходит в состояние rejected, то Promise.race() возвращает ошибку этого промиса.

Важно отличать Promise.race() от Promise.any(). Promise.any() также ждёт первый успешно выполненный промис, но игнорирует отклонённые, пока не найдёт хотя бы один успешный. Promise.race() же завершается на первом любом результате - будь то успех или ошибка.

Метод полезен для установки таймаутов, когда нужно ограничить время ожидания ответа от сервера, или для выбора самого быстрого источника данных из нескольких.

На практике

В тестировании API и веб-приложений Promise.race() часто применяется для:

  • ограничения времени выполнения теста (timeout)
  • сравнения скорости ответа от разных эндпоинтов
  • реализации fallback-механизмов, когда нужно дождаться первого успешного ответа из нескольких источников
  • проверки, что запрос действительно отклоняется быстрее, чем успешный ответ

При этом нужно помнить: если первый завершившийся промис упадёт с ошибкой, Promise.race() сразу перейдёт в rejected, даже если другие промисы ещё выполняются и могли бы завершиться успешно.

Пример кода

JAVASCRIPT
// Пример с таймаутом для HTTP-запроса
function fetchWithTimeout(url, timeoutMs = 5000) {
const fetchPromise = fetch(url);
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => reject(new Error('Request timed out')), timeoutMs)
);
return Promise.race([fetchPromise, timeoutPromise]);
}
// Пример: выбор самого быстрого источника данных
const source1 = fetch('/api/data1');
const source2 = fetch('/api/data2');
const source3 = fetch('/api/data3');
Promise.race([source1, source2, source3])
.then(response => {
console.log('Первый ответ получен:', response.url);
})
.catch(error => {
console.error('Первый завершившийся запрос упал с ошибкой:', error);
});

Как отвечать на собеседовании

Начни с прямого ответа: Promise.race(). Затем кратко объясни его поведение - завершается на первом любом результате (успех или ошибка). Подчеркни отличие от Promise.any(), который игнорирует ошибки до первого успеха. Приведи практический пример использования - таймаут для запроса. Если спросят про альтернативы, упомяни Promise.any() и Promise.allSettled(), но чётко разграничь их назначение. Хорошо показать понимание edge case: если первый промис упадёт с ошибкой, Promise.race() сразу reject, даже если другие промисы ещё выполняются.

Что проверяет интервьюер

  • Знание статических методов Promise и их различий
  • Понимание асинхронности и event loop
  • Умение применять Promise.race() в реальных сценариях (таймауты, fallback)
  • Способность объяснить поведение при ошибках и race condition
  • Понимание, что Promise.race() не отменяет остальные промисы - они продолжают выполняться

Типичные ошибки

  • Путают Promise.race() с Promise.any() - не различают реакцию на первый reject
  • Думают, что Promise.race() отменяет остальные промисы - на самом деле они продолжают выполняться в фоне
  • Используют Promise.race() для ожидания первого успешного результата, игнорируя ошибки - для этого нужен Promise.any()
  • Забывают обработать reject в catch, полагая, что race всегда вернёт успешный результат
  • Передают в Promise.race() неитерируемый объект или пустой массив - в последнем случае промис зависнет навсегда

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью