> Какой тип данных должна возвращать функция retry в JavaScript (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Яндекс
Стек: JavaScript
> Пример ответа
Короткий ответ
Функция retry должна возвращать Promise. Это необходимо, потому что повторная попытка выполнения асинхронной операции - по определению асинхронный процесс. Даже если исходная функция синхронная, механизм повторных попыток с задержками и учётом количества попыток требует асинхронного управления. Возвращая Promise, retry позволяет вызывающему коду использовать await или .then(), корректно обрабатывать успех и ошибку после всех попыток.
Подробное объяснение
retry - это утилита, которая принимает функцию (часто асинхронную) и повторяет её выполнение при ошибке до заданного числа попыток. Возврат Promise - единственный правильный выбор по нескольким причинам:
- Асинхронность повторных попыток: между попытками обычно нужна задержка (backoff), что требует
setTimeoutилиsleep. Это асинхронные операции, их нельзя синхронно дождаться. - Единый интерфейс: вызывающий код всегда работает с
Promise, независимо от того, сколько попыток потребовалось. Это упрощает композицию с другими асинхронными функциями. - Обработка ошибок:
Promiseпредоставляет чёткий механизм: resolve при успехе на любой попытке, reject после исчерпания всех попыток. Это позволяет использоватьtry/catchили.catch(). - Совместимость с async/await:
retryсама может бытьasyncфункцией, которая неявно возвращаетPromise. Это стандартный паттерн в современном JavaScript.
Если бы retry возвращала, например, undefined или Error, вызывающий код не мог бы дождаться завершения повторных попыток и получить результат.
На практике
В реальных проектах retry часто используется для:
- HTTP-запросов к ненадёжным API (сетевая ошибка, таймаут)
- Операций с базой данных (deadlock, временная недоступность)
- Работы с внешними сервисами (rate limit, 503)
Типичная сигнатура: retry(fn, options) где options - { retries: number, delay: number, backoff: 'fixed' | 'exponential' }. Возвращаемый Promise разрешается значением fn при успехе или отклоняется последней ошибкой.
Важно: retry не должна повторять попытки при "фатальных" ошибках (например, 4xx для HTTP), поэтому внутри fn часто выбрасывают ошибки только для retriable случаев.
Пример кода
JAVASCRIPTasync function retry(fn, { retries = 3, delay = 1000, backoff = 'exponential' } = {}) {let lastError;for (let attempt = 0; attempt <= retries; attempt++) {try {return await fn(attempt); // возвращаем успешный результат} catch (error) {lastError = error;if (attempt === retries) break; // последняя попытка - не ждёмconst waitTime = backoff === 'exponential' ? delay * Math.pow(2, attempt) : delay;await new Promise(resolve => setTimeout(resolve, waitTime));}}throw lastError; // reject с последней ошибкой}// Использованиеconst data = await retry(() => fetch('/api/data'), { retries: 5 });
Как отвечать на собеседовании
Начни с чёткого утверждения: "Функция retry должна возвращать Promise". Объясни, что это асинхронный паттерн, и приведи аргументы из раздела "Подробное объяснение". Если интервьюер спросит про альтернативы (колбэки, синхронные повторы), объясни, почему они хуже: колбэки ведут к callback hell, синхронные повторы блокируют event loop и не позволяют делать задержки. Покажи пример кода с async/await - это современный стандарт. Упомяни, что retry может быть реализована и без async, через явное создание Promise, но async чище.
Что проверяет интервьюер
- Понимание асинхронности в JavaScript: event loop, Promise, async/await.
- Умение проектировать API: почему возврат
Promise- правильный контракт. - Знание практических паттернов: retry, backoff, обработка ошибок.
- Способность объяснить trade-off: почему не колбэк, не синхронный вызов.
- Внимание к деталям: что делать с последней ошибкой, как передавать результат.
Типичные ошибки
- Возврат
undefinedилиnullизretry- вызывающий код не может дождаться результата. - Использование синхронного цикла с
setTimeoutбезPromise- задержки не сработают, функция завершится мгновенно. - Возврат
Promise, который разрешается сразу, без ожидания попыток - теряется смысл retry. - Неправильная обработка последней ошибки: возврат успеха после всех неудач или потеря ошибки.
- Игнорирование фатальных ошибок: retry на 404 или 400 только ухудшит ситуацию.
> Похожие задачи по frontend
В чем отличие контекста в строгом режиме и без него в JavaScript
Как использовать resolve и reject внутри callback для управления состоянием Promise в JavaScript
Почему нельзя использовать Map вместо объекта для возвращаемого значения метода groupBy в JavaScript
Как создать собственную функцию executor в Promise в JavaScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью