> Как реализовать тайм-аут для асинхронного запроса, если ответ приходит дольше одной секунды в JavaScript? (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Яндекс
Стек: JavaScript
> Пример ответа
Короткий ответ
Тайм-аут для асинхронного запроса реализуется через AbortController в связке с fetch или через Promise.race с таймером. AbortController является предпочтительным, так как он не только отклоняет промис, но и отменяет сам HTTP-запрос, предотвращая лишнюю нагрузку. Для Promise.race запрос продолжает выполняться в фоне, что может быть проблемой при большом количестве запросов.
Подробное объяснение
Основная задача - прервать ожидание ответа, если он не пришёл за заданное время. Есть два подхода:
-
AbortController(рекомендуется): создаётся сигнал, который передаётся вfetch. ЧерезsetTimeoutвызываетсяabort(), что генерирует исключениеAbortError. Запрос физически отменяется на уровне сети. -
Promise.race: соревнуются промис запроса и промис таймера (отклоняется черезsetTimeout). Минус - запрос не отменяется, продолжает выполняться и потреблять ресурсы.
Для fetch тайм-аут не встроен, поэтому используется AbortController. Для XMLHttpRequest есть свойство timeout и событие ontimeout.
На практике
В реальных проектах тайм-аут часто комбинируют с повторными попытками (retry) и обработкой ошибок сети. Важно очищать таймер при успешном ответе, чтобы избежать утечек. AbortController поддерживается всеми современными браузерами и Node.js 15+.
Пример кода
JAVASCRIPTasync 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для нескольких запросов
> Похожие задачи по frontend
Как реализовать декоратор функции в JavaScript, ограничивающий число вызовов и вызывающий колбэк при последнем вызове
Что содержит this в обработчике события на кнопку в JavaScript
Нужно ли использовать замыкания при обработке результатов нескольких асинхронных запросов в JavaScript?
Есть ли разница между вызовом setTimeout с нулевой задержкой и без тайминга в JavaScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью