> Как рекурсивно проверять условие повторных запросов с учётом счётчика попыток в JavaScript (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Яндекс
Стек: JavaScript
> Пример ответа
Короткий ответ
Рекурсивная проверка с учётом счётчика попыток реализуется через функцию, которая принимает условие повторения и максимальное количество попыток. На каждом шаге проверяется условие, и если оно истинно, а счётчик не исчерпан, функция вызывает себя с уменьшенным счётчиком. Базовый случай - когда условие ложно или счётчик достиг нуля. Это позволяет избежать бесконечной рекурсии и контролировать количество повторений.
Подробное объяснение
Рекурсивный подход к повторным запросам основан на двух ключевых элементах: условии повторения и счётчике попыток. Условие может быть функцией, возвращающей boolean, или результатом асинхронной операции (например, fetch). Счётчик попыток передаётся как аргумент и уменьшается на каждом шаге.
Базовый случай рекурсии - когда условие не выполняется (успех) или счётчик достиг нуля (исчерпаны попытки). В случае успеха функция возвращает результат, в случае неудачи - выбрасывает ошибку или возвращает fallback-значение.
Рекурсивный вызов происходит только если условие истинно и счётчик > 0. Для асинхронных операций используется async/await или then/catch. Важно учитывать стек вызовов: глубокая рекурсия может привести к stack overflow, поэтому для большого числа попыток лучше использовать итеративный подход.
На практике
В реальных проектах такой паттерн применяется для retry-логики при сетевых запросах, polling (периодической проверке состояния), повторных попытках подключения к WebSocket или при обработке rate limiting. Обычно добавляют задержку между попытками (exponential backoff) и логирование.
Счётчик попыток должен быть разумным - 3-5 попыток для сетевых запросов, больше для polling. Важно передавать счётчик как параметр, а не использовать глобальную переменную, чтобы избежать side effects и обеспечить чистоту функции.
Пример кода
JAVASCRIPTasync function retryWithCondition(conditionFn, maxAttempts, delay = 1000) {const attempt = async (remaining) => {if (remaining <= 0) {throw new Error('All attempts exhausted');}try {const result = await conditionFn();if (result) {// Условие выполнилось - повторяемawait new Promise(resolve => setTimeout(resolve, delay));return attempt(remaining - 1);}// Условие не выполнилось - успехreturn result;} catch (error) {// Ошибка выполнения - повторяемif (remaining > 1) {await new Promise(resolve => setTimeout(resolve, delay));return attempt(remaining - 1);}throw error;}};return attempt(maxAttempts);}// Использованиеconst checkStatus = async () => {const response = await fetch('/api/status');const data = await response.json();return data.status === 'pending'; // true = повторяем};retryWithCondition(checkStatus, 3, 2000).then(() => console.log('Status confirmed')).catch(err => console.error('Failed:', err));
Как отвечать на собеседовании
Начни с базового определения рекурсивной проверки со счётчиком. Объясни структуру: условие, счётчик, базовый случай. Покажи понимание асинхронного варианта с async/await. Упомяни trade-off между рекурсией и итерацией (стек вызовов vs читаемость). Добавь про exponential backoff и обработку ошибок. Если спросят про оптимизацию, предложи хвостовую рекурсию или trampoline.
Что проверяет интервьюер
- Понимание рекурсии и базового случая
- Умение работать с асинхронностью в JavaScript
- Навыки обработки ошибок и краевых случаев
- Знание практических паттернов (retry, polling)
- Способность оценить trade-off между рекурсией и циклом
Типичные ошибки
- Забывают про базовый случай - бесконечная рекурсия
- Используют глобальный счётчик вместо параметра
- Не обрабатывают ошибки внутри conditionFn
- Не учитывают stack overflow при большом числе попыток
- Путают условие повторения с условием остановки (логика инвертирована)
- Не добавляют задержку между попытками, создавая лишнюю нагрузку
> Похожие задачи по frontend
Почему var всплывает и что происходит при всплытии в JavaScript
Как реализовать обработку клика на любой div внутри root и выводить в консоль только id этого div в JavaScript
Что делать в функции каррирования в JavaScript при получении достаточного количества аргументов
Блокируется ли поток при выполнении асинхронного кода после синхронного в JavaScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью