> В каком порядке выполняются console.log в JavaScript с учетом синхронности и микротасков? (JavaScript)

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

Компании: РСХБ

Стек: JavaScript

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

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

Порядок выполнения console.log в JavaScript определяется event loop: сначала выполняется весь синхронный код, затем микротаски (Promise.then, queueMicrotask, MutationObserver), потом макротаски (setTimeout, setInterval, I/O). Микротаски обрабатываются до начала следующей макротаски, даже если они добавляются во время выполнения другой микротаски.

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

JavaScript - однопоточный язык с неблокирующим event loop. Код выполняется в следующем порядке:

  1. Синхронный код - выполняется немедленно в текущем стеке вызовов (call stack). Все console.log, не обёрнутые в асинхронные API, попадают сюда.

  2. Микротаски - после завершения синхронного кода, перед каждой макротаской, event loop проверяет очередь микротасков. Сюда входят:

    • Promise.then/catch/finally
    • queueMicrotask
    • MutationObserver
    • process.nextTick (Node.js, выполняется до остальных микротасков)
  3. Макротаски - выполняются после того, как очередь микротасков опустела. Сюда входят:

    • setTimeout/setInterval
    • setImmediate (Node.js)
    • I/O (чтение файлов, сетевые запросы)
    • UI rendering (браузер)

Ключевой момент: если во время выполнения микротаски добавляется новая микротаска, она выполняется до перехода к макротаскам. Это может привести к бесконечному циклу, если не контролировать глубину.

На практике

Для senior-разработчика важно понимать, что порядок выполнения влияет на:

  • Обработку ошибок в асинхронных цепочках
  • Время доступа к DOM после обновления состояния
  • Производительность при большом количестве микротасков (например, рекурсивные Promise)

Пример типичного сценария: если в Promise.then добавить ещё один Promise.then, он выполнится до setTimeout, даже если setTimeout был зарегистрирован раньше по времени.

Пример кода

JAVASCRIPT
console.log('1: sync');
setTimeout(() => {
console.log('2: macro');
}, 0);
Promise.resolve().then(() => {
console.log('3: micro');
});
Promise.resolve().then(() => {
Promise.resolve().then(() => {
console.log('4: nested micro');
});
console.log('5: micro after nested');
});
console.log('6: sync end');
// Вывод:
// 1: sync
// 6: sync end
// 3: micro
// 5: micro after nested
// 4: nested micro
// 2: macro

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

Начни с краткого определения event loop, затем перечисли порядок: синхронный код → микротаски → макротаски. Приведи пример с вложенными микротасками, чтобы показать понимание их приоритета. Упомяни, что микротаски блокируют макротаски, если добавляются рекурсивно. Не углубляйся в детали реализации V8 или Node.js, если не спрашивают.

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

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

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

  • Путать микротаски и макротаски (например, считать setTimeout микротаской)
  • Думать, что setTimeout с задержкой 0 выполняется сразу после синхронного кода
  • Не учитывать, что вложенные микротаски выполняются до макротасок
  • Забывать про process.nextTick в Node.js (выполняется до Promise.then)

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

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