> Каков порядок вывода консольных логов при использовании setTimeout и промисов в JavaScript (JavaScript)

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

Компании: amoCRM

Стек: JavaScript

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

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

Порядок вывода определяется event loop: сначала выполняются синхронные задачи, затем микрозадачи (промисы), потом макрозадачи (setTimeout). Таким образом, resolve промиса выведется раньше, чем колбэк setTimeout, даже если таймер установлен на 0 мс.

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

JavaScript использует однопоточную модель с event loop. Очередь задач делится на три уровня:

  1. Синхронный код - выполняется сразу в текущем стеке вызовов.
  2. Микрозадачи (microtasks) - промисы (then/catch/finally), queueMicrotask, MutationObserver. Выполняются сразу после завершения текущего синхронного кода, перед любой макрозадачей.
  3. Макрозадачи (macrotasks) - setTimeout, setInterval, I/O, UI rendering. Выполняются по одной за цикл event loop.

Когда промис переходит в состояние resolved или rejected, его колбэк попадает в очередь микрозадач. setTimeout добавляет колбэк в очередь макрозадач. Event loop сначала опустошает очередь микрозадач, затем берёт одну макрозадачу.

На практике

Это поведение критично при построении цепочек асинхронных операций. Если нужно гарантировать выполнение после всех микрозадач - используйте setTimeout. Если нужно выполнить код как можно раньше после синхронной части - используйте Promise.resolve().then() или queueMicrotask.

Пример кода

JAVASCRIPT
console.log('1: синхронный');
setTimeout(() => console.log('2: setTimeout'), 0);
Promise.resolve().then(() => console.log('3: промис'));
console.log('4: синхронный');

Вывод:

1: синхронный
4: синхронный
3: промис
2: setTimeout

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

Начни с event loop и разделения на очереди. Объясни, что микрозадачи имеют приоритет над макрозадачами. Приведи пример с setTimeout(0) и промисом. Упомяни, что вложенные микрозадачи (например, then внутри then) выполняются до перехода к следующей макрозадаче. Если спросят про async/await - объясни, что await - это синтаксический сахар над then, и код после await попадает в микрозадачи.

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

  • Понимание event loop и очередей задач
  • Различие между микрозадачами и макрозадачами
  • Умение предсказывать порядок выполнения асинхронного кода
  • Знание приоритетов разных типов асинхронных операций

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

  • Утверждение, что setTimeout(0) выполняется мгновенно
  • Игнорирование разницы между микрозадачами и макрозадачами
  • Непонимание, что вложенные промисы создают новые микрозадачи
  • Путаница между async/await и обычными промисами в контексте event loop

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

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