> Как реализовать тайм-аут для асинхронного запроса, если ответ приходит дольше одной секунды в JavaScript? (JavaScript)

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

Компании: Яндекс

Стек: JavaScript

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

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

Тайм-аут для асинхронного запроса реализуется через AbortController в связке с fetch или через Promise.race с таймером. AbortController является предпочтительным, так как он не только отклоняет промис, но и отменяет сам HTTP-запрос, предотвращая лишнюю нагрузку. Для Promise.race запрос продолжает выполняться в фоне, что может быть проблемой при большом количестве запросов.

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

Основная задача - прервать ожидание ответа, если он не пришёл за заданное время. Есть два подхода:

  1. AbortController (рекомендуется): создаётся сигнал, который передаётся в fetch. Через setTimeout вызывается abort(), что генерирует исключение AbortError. Запрос физически отменяется на уровне сети.

  2. Promise.race: соревнуются промис запроса и промис таймера (отклоняется через setTimeout). Минус - запрос не отменяется, продолжает выполняться и потреблять ресурсы.

Для fetch тайм-аут не встроен, поэтому используется AbortController. Для XMLHttpRequest есть свойство timeout и событие ontimeout.

На практике

В реальных проектах тайм-аут часто комбинируют с повторными попытками (retry) и обработкой ошибок сети. Важно очищать таймер при успешном ответе, чтобы избежать утечек. AbortController поддерживается всеми современными браузерами и Node.js 15+.

Пример кода

JAVASCRIPT
async function fetchWithTimeout(url, timeoutMs = 1000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, { signal: controller.signal });
return response;
} catch (error) {
if (error.name === 'AbortError') {
throw new Error(`Request timed out after ${timeoutMs}ms`);
}
throw error;
} finally {
clearTimeout(timeoutId);
}
}
// Использование
try {
const data = await fetchWithTimeout('https://api.example.com/data', 1000);
} catch (err) {
console.error(err.message);
}

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

Начни с AbortController как основного решения, упомяни Promise.race как альтернативу с оговоркой про неотменённый запрос. Объясни, почему очистка таймера важна. Если спросят про старые браузеры - упомяни XMLHttpRequest.timeout. Покажи понимание trade-off между простотой и производительностью.

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

  • Знание современного API (AbortController)
  • Понимание асинхронности и управления промисами
  • Умение обрабатывать ошибки и очищать ресурсы
  • Осознание разницы между отклонением промиса и фактической отменой запроса

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

  • Забывают очистить таймер в finally, что приводит к утечкам
  • Используют Promise.race без учёта, что запрос продолжает выполняться
  • Не обрабатывают AbortError отдельно от других ошибок сети
  • Пытаются повторно использовать один AbortController для нескольких запросов

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

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