> Что такое event loop в JavaScript и как он работает с микрозадачами и макрозадачами (JavaScript)

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

Компании: amoCRM, Иннотех, Cyber Interactive, Альфа-банк, YADRO, Garage Eight, Kvando Technologies, циан, Soft_Media_Group, ООО Премиум ИТ Солюшен, VK, Kodix, РСХБ, LeverX, Инити, Aston, Газпромбанк, Домклик, IT-One, Софт Медиа Групп, МТГ Бизнес решения, Библио-Глобус, Rutube, Дом.рф, intelsy, Avito, Сфера, EdenAI, Сбер, Арго, TYMY, 1221 Systems, Исходный Код, Globaldrive, Кэтрид Диджитал, SmartWay, ООО Снэп АйТи

Стек: JavaScript

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

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

Event loop - это механизм в JavaScript, который управляет порядком выполнения кода, обрабатывая очередь задач. Он позволяет синхронному языку работать асинхронно: сначала выполняются все синхронные операции, затем микрозадачи (promises, queueMicrotask), и только потом макрозадачи (setTimeout, setInterval, I/O). Микрозадачи всегда выполняются до следующей макрозадачи, что гарантирует предсказуемый порядок асинхронных операций.

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

JavaScript - однопоточный язык с одним call stack. Event loop - это бесконечный цикл, который проверяет, пуст ли call stack, и если да, берёт задачи из очередей.

Существует две очереди:

  • Микрозадачи - создаются через Promise.then, catch, finally, queueMicrotask, async/await (после await). Они имеют приоритет.
  • Макрозадачи - создаются через setTimeout, setInterval, setImmediate, I/O, рендеринг браузера.

Алгоритм работы event loop:

  1. Выполнить весь синхронный код (текущий call stack).
  2. После того как стек пуст, выполнить все микрозадачи из очереди (по одной, но до полного опустошения).
  3. Взять одну макрозадачу из очереди и выполнить её.
  4. После выполнения макрозадачи снова проверить микрозадачи - если появились новые, выполнить их все.
  5. Повторять цикл.

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

Рендеринг браузера происходит между макрозадачами, но после микрозадач. Поэтому если вы обновляете DOM в микрозадаче, браузер может не успеть отрисовать до следующей макрозадачи.

На практике

Понимание event loop критично для:

  • отладки асинхронного кода - порядок выполнения не всегда очевиден;
  • оптимизации производительности - тяжёлые операции в микрозадачах блокируют рендеринг;
  • работы с async/await - await всегда создаёт микрозадачу, даже если промис уже resolved;
  • избегания deadlock-подобных ситуаций, когда микрозадачи бесконечно порождают себя.

Пример кода

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

Обратите внимание: все микрозадачи выполняются до макрозадачи, даже если setTimeout с нулевой задержкой был вызван раньше.

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

Начните с простого определения, затем опишите порядок выполнения. Обязательно упомяните, что микрозадачи имеют приоритет над макрозадачами. Приведите пример с setTimeout и Promise. Если спросят про async/await - скажите, что await - это синтаксический сахар над промисами, и он тоже создаёт микрозадачу.

Для уровня junior достаточно объяснить базовый механизм и порядок. Не углубляйтесь в детали реализации V8 или Node.js, если не спрашивают.

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

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

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

  • Утверждение, что setTimeout(0) выполнится сразу после синхронного кода - на самом деле после всех микрозадач.
  • Забывают, что микрозадачи выполняются все подряд, а макрозадачи - по одной за итерацию.
  • Путают порядок: думают, что макрозадачи и микрозадачи чередуются.
  • Не знают, что await всегда создаёт микрозадачу, даже если промис уже resolved.
  • Считают, что event loop - это часть языка JavaScript, хотя это часть окружения (браузер или Node.js).

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

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