> Как колбэк из setTimeout попадает к выполнению? (JavaScript)

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

Компании: Дом.рф

Стек: JavaScript

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

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

Колбэк из setTimeout попадает в очередь макрозадач (macrotask queue) после истечения таймера. Event loop на каждой итерации проверяет, пуст ли стек вызовов (call stack), и если да - берёт первый колбэк из очереди макрозадач и помещает его в стек для выполнения. Точное время срабатывания зависит от текущей загрузки стека и других задач в очереди.

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

Когда вызывается setTimeout(fn, delay), браузер запускает таймер в среде выполнения (Web API). По истечении delay миллисекунд колбэк fn помещается в очередь макрозадач. Event loop непрерывно мониторит стек вызовов: если стек пуст и очередь макрозадач не пуста, он извлекает первый колбэк из очереди и помещает его в стек. Это гарантирует, что колбэк не выполнится, пока не завершатся все синхронные операции и микрозадачи (например, Promise.then). Задержка delay - минимальное время до помещения в очередь, а не гарантированное время выполнения.

На практике

  • Если стек занят долгим синхронным кодом, колбэк setTimeout задержится, даже если таймер уже истёк.
  • Вложенные setTimeout с нулевой задержкой создают последовательность макрозадач, что может использоваться для разбиения тяжёлых вычислений.
  • Для точного тайминга анимаций лучше использовать requestAnimationFrame, так как setTimeout не синхронизирован с частотой обновления экрана.
  • Минимальная задержка в браузерах обычно 4 мс для вложенных таймеров (HTML spec).

Пример кода

JAVASCRIPT
console.log('1: синхронный код');
setTimeout(() => {
console.log('3: колбэк setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('2: микрозадача Promise');
});
console.log('4: ещё синхронный код');
// Вывод:
// 1: синхронный код
// 4: ещё синхронный код
// 2: микрозадача Promise
// 3: колбэк setTimeout

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

Начни с краткого описания event loop и очереди макрозадач. Объясни, что setTimeout не гарантирует точное время выполнения - только минимальную задержку. Упомяни различие между макрозадачами и микрозадачами, приведи пример с Promise. Покажи понимание, что колбэк выполняется только когда стек пуст. Если спросят про вложенные таймеры, расскажи про clamping задержки до 4 мс.

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

  • Понимание event loop и асинхронности в JavaScript.
  • Знание разницы между макрозадачами и микрозадачами.
  • Умение объяснить, почему setTimeout(fn, 0) не выполняется мгновенно.
  • Осознание, что таймер - это минимальная задержка, а не гарантированное время.
  • Способность предсказать порядок вывода в примере с микрозадачами.

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

  • Утверждение, что setTimeout(fn, 0) выполняется сразу после синхронного кода.
  • Путаница между очередью микрозадач и макрозадач.
  • Игнорирование влияния загруженности стека на время выполнения колбэка.
  • Уверенность, что задержка в setTimeout - точное время выполнения.
  • Непонимание, что таймеры управляются не самим JavaScript, а окружением (браузер/Node.js).

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

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