> Каков порядок выполнения задач (task) и микротасков (microtask) в JavaScript (JavaScript)

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

Компании: циан, IT-One, Purrweb, SmartWay

Стек: JavaScript

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

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

В JavaScript event loop сначала выполняет один макротаск (task) из очереди, затем обрабатывает всю очередь микротасков (microtask), после чего переходит к рендерингу (если требуется), и повторяет цикл. Микротаски имеют приоритет над макротасками и выполняются до начала следующего макротаска. Это гарантирует, что промисы и MutationObserver обрабатываются быстрее, чем setTimeout или события ввода.

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

Event loop в JavaScript работает по следующему алгоритму:

  1. Выполняется текущий синхронный код (глобальный скрипт - это тоже макротаск).
  2. Из очереди макротасков (task queue) извлекается один самый старый макротаск и выполняется.
  3. После завершения макротаска проверяется очередь микротасков (microtask queue). Все микротаски выполняются последовательно, пока очередь не опустеет. Если во время выполнения микротаска добавляются новые микротаски, они тоже выполняются в этом же цикле.
  4. После очистки очереди микротасков может произойти рендеринг (обновление DOM, вычисление стилей, repaint), если браузер решит, что это необходимо.
  5. Цикл повторяется: берётся следующий макротаск.

К макротаскам относятся: setTimeout, setInterval, setImmediate (Node.js), I/O, события UI (click, keydown), рендеринг.

К микротаскам относятся: Promise.then/catch/finally, queueMicrotask, MutationObserver, process.nextTick (Node.js).

Важно: микротаски могут блокировать event loop, если они добавляют новые микротаски бесконечно - браузер не сможет перейти к рендерингу или следующему макротаску.

На практике

  • Promise.then выполняется до setTimeout с нулевой задержкой, даже если setTimeout был вызван раньше.
  • Если в микротаске создать новый промис и зарезолвить его, его then тоже выполнится в текущем цикле микротасков.
  • В Node.js process.nextTick имеет ещё более высокий приоритет, чем Promise.then, и выполняется до других микротасков.
  • MutationObserver срабатывает как микротаск, поэтому изменения DOM обрабатываются до следующего рендеринга.
  • Для асинхронных операций, которые не требуют немедленного выполнения, лучше использовать макротаски (setTimeout), чтобы не блокировать UI.

Пример кода

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

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

Начни с краткого определения event loop и приоритета микротасков. Затем опиши пошаговый алгоритм выполнения. Обязательно приведи пример с промисом и setTimeout, чтобы показать разницу. Упомяни, что микротаски могут блокировать поток, если их бесконечно добавлять. Если спросят про Node.js, добавь про process.nextTick. Не углубляйся в детали реализации V8, если не попросят.

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

  • Понимание основ event loop и асинхронности в JavaScript.
  • Умение различать макротаски и микротаски.
  • Знание, какие API относятся к каждой категории.
  • Понимание, что микротаски выполняются до рендеринга и следующего макротаска.
  • Способность предсказать порядок вывода в коде с асинхронными операциями.

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

  • Утверждение, что микротаски выполняются после всех макротасков - это неверно, они выполняются после каждого макротаска.
  • Путаница между setTimeout(fn, 0) и Promise.resolve().then - многие думают, что setTimeout выполнится первым, если вызван раньше.
  • Игнорирование того, что микротаски, добавленные во время выполнения микротасков, тоже обрабатываются в текущем цикле.
  • Забывают про рендеринг между циклами event loop.
  • В Node.js путают process.nextTick с обычными микротасками (он выполняется раньше).

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

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