← Назад к вопросам

Event Loop: определите порядок вывода

1.7 Middle🔥 291 комментариев
#Node.js и JavaScript#Алгоритмы и структуры данных

Условие

Дан следующий код:

console.log(1);
setTimeout(() => console.log(2));
Promise.resolve().then(() => console.log(3));
Promise.resolve().then(() => setTimeout(() => console.log(4)));
Promise.resolve().then(() => console.log(5));
setTimeout(() => console.log(6));
console.log(7);

Определите порядок вывода чисел в консоль и объясните почему.

Что проверяется

  • Понимание Event Loop в Node.js
  • Разница между микрозадачами (Promise.then) и макрозадачами (setTimeout)
  • Порядок выполнения синхронного и асинхронного кода

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение

Порядок вывода

1
7
3
5
2
4
6

Объяснение

Event Loop в Node.js работает в несколько фаз, и критически важно различать:

  1. Синхронный код — выполняется сразу
  2. Микрозадачи (microtask queue) — Promise.then(), Promise.catch(), queueMicrotask()
  3. Макрозадачи (macrotask queue) — setTimeout(), setInterval(), setImmediate()

Порядок выполнения в каждом цикле:

  1. Выполнить весь синхронный код
  2. Выполнить все микрозадачи из микроочереди
  3. Выполнить одну макрозадачу
  4. Вернуться к шагу 2

Пошаговый разбор кода

Этап 1: Синхронный код (Call Stack)

console.log(1);              // ✓ Вывод: 1
setTimeout(() => ...);       // Добавляется в macrotask queue
Promise.resolve().then(...); // Добавляется в microtask queue
Promise.resolve().then(...); // Добавляется в microtask queue
Promise.resolve().then(...); // Добавляется в microtask queue
setTimeout(() => ...);       // Добавляется в macrotask queue
console.log(7);              // ✓ Вывод: 7

После синхронного кода:

  • Call Stack: пуст
  • Microtask Queue: [then1, then2, then3]
  • Macrotask Queue: [setTimeout1, setTimeout2]

Этап 2: Обработка микрозадач

Выполняется then1 (первый Promise.resolve().then):

() => console.log(3)  // ✓ Вывод: 3

Выполняется then2 (второй Promise.resolve().then):

() => {
  setTimeout(() => console.log(4))  // Добавляется в macrotask queue
}

Выполняется then3 (третий Promise.resolve().then):

() => console.log(5)  // ✓ Вывод: 5

После микрозадач:

  • Microtask Queue: пуст
  • Macrotask Queue: [setTimeout1 (выводит 2), setTimeout2 (выводит 6), setTimeout3 (выводит 4)]

Этап 3: Обработка макрозадач

Выполняется первая макрозадача — setTimeout1:

() => console.log(2)  // ✓ Вывод: 2

Event Loop проверяет микрозадачи — их нет. Переходит ко второй макрозадаче — setTimeout2:

() => console.log(6)  // ✓ Вывод: 6

Event Loop проверяет микрозадачи — их нет. Переходит к третьей макрозадаче — setTimeout3:

() => console.log(4)  // ✓ Вывод: 4

Диаграмма выполнения

Этап 1: СИНХРОННЫЙ КОД
├─ console.log(1)      → Вывод: 1
├─ setTimeout → queue_macro
├─ Promise.then → queue_micro #1
├─ Promise.then → queue_micro #2
├─ Promise.then → queue_micro #3
├─ setTimeout → queue_macro
└─ console.log(7)      → Вывод: 7

Этап 2: МИКРОЗАДАЧИ
├─ queue_micro #1 → Вывод: 3
├─ queue_micro #2 → setTimeout → queue_macro
└─ queue_micro #3 → Вывод: 5

Этап 3: МАКРОЗАДАЧИ (одна за раз)
├─ setTimeout #1 → Вывод: 2
├─ setTimeout #2 → Вывод: 6
└─ setTimeout #3 → Вывод: 4

Ключевые моменты

  • Promise.then привязывает микрозадачи, которые выполняются ДО следующей макрозадачи
  • setTimeout всегда идёт в macrotask queue, даже если вызван из Promise
  • Порядок: синхронный код → все микрозадачи → одна макрозадача → повтор
  • Это одна из самых частых ошибок в собеседованиях — путаница между priority микро и макрозадач