> Какой тип данных должна возвращать функция 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 случаев.

Пример кода

JAVASCRIPT
async 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 только ухудшит ситуацию.

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

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