Skip to main content

З яких фаз складається Event Loop?

1. Що таке "фаза" Event Loop

Event Loop у Node.js реалізовано через бібліотеку libuv. Кожна ітерація (цикл) Event Loop ділиться на фази - логічні етапи, на яких виконуються різні типи callback-ів.

Одна ітерація Event Loop називається tick. Після виконання всіх фаз цикл починається знову (поки є задачі).

2. Основні фази Event Loop

ФазаЩо робитьПриклади callback-ів
1timersВиконує callback-и від setTimeout() і setInterval()setTimeout(cb, 0)
2pending callbacksВиконує деякі відкладені системні callback-и (помилки I/O, TCP тощо)Помилки сокетів, TCP.onconnection
3idle, prepareВнутрішні фази libuv (не використовуються напряму в JS)-
4pollОсновна фаза очікування I/O. Виконує готові I/O callback-и або чекає нових подійfs.readFile(), мережеві події
5checkВиконує callback-и від setImmediate()setImmediate(cb)
6close callbacksВиконує callback-и закриття ресурсівsocket.on('close'), stream.destroy()

3. Схематично (в одній ітерації Event Loop):

javascript
┌───────────────────────────────────────┐ 1. timers │ ← setTimeout(), setInterval() ├───────────────────────────────────────┤ 2. pending callbacks │ ← системні callback-и (I/O) ├───────────────────────────────────────┤ 3. idle, prepare │ ← внутрішні фази libuv ├───────────────────────────────────────┤ 4. poll │ ← очікування й обробка I/O подій ├───────────────────────────────────────┤ 5. check │ ← setImmediate() ├───────────────────────────────────────┤ 6. close callbacks │ ← socket.on('close'), stream.on('close') └───────────────────────────────────────┘

Після цього - нова ітерація (tick).

4. Як пов'язані setTimeout() і setImmediate()

Дуже часто питають на співбесідах.

ФункціяДе виконуєтьсяКоли приблизно
setTimeout(cb, 0)timersНа початку наступного циклу Event Loop
setImmediate(cb)checkНаприкінці поточного циклу Event Loop

Приклад:

javascript
setTimeout(() => console.log('timeout'), 0); setImmediate(() => console.log('immediate'));

Результат може бути:

javascript
timeout immediate

або

javascript
immediate timeout

Усе залежить від того, де було запущено код - до чи після I/O.

5. Особлива черга microtasks

Крім фаз Event Loop, є мікрозадачі (microtasks) - це callback-и від:

  • Promise.then() / catch() / finally();
  • process.nextTick().

Вони не належать жодній фазі, але виконуються між фазами - після кожного виконаного callback-а Event Loop виконуються всі microtasks.

Пріоритет:

  1. process.nextTick() - виконується перед microtasks.
  2. Microtasks (Promise.then, queueMicrotask).
  3. Далі - перехід до наступної фази Event Loop.

6. Приклад із промисами й nextTick

javascript
setTimeout(() => console.log('timeout'), 0); Promise.resolve().then(() => console.log('promise')); process.nextTick(() => console.log('nextTick')); setImmediate(() => console.log('immediate'));

Результат:

javascript
nextTick promise timeout immediate

Чому:

  1. nextTick і promise → черга microtask;
  2. потім фаза timers (timeout);
  3. потім фаза check (immediate).

7. Особливості фаз poll і check

Фаза poll:

  • Основна фаза Event Loop.
  • Саме тут Node.js чекає нових I/O подій.
  • Якщо черга порожня:
    • і є таймери → Event Loop перейде у фазу timers;
    • якщо немає → Event Loop засне, чекаючи I/O.

Фаза check:

  • Виконує callback-и setImmediate().
  • Якщо poll завершився раніше (без подій), керування швидко передається в check.

8. Фаза close callbacks

Завершує цикл:

  • виконує callback-и, пов'язані із закриттям ресурсів (close, destroy, disconnect);
  • наприклад, після socket.destroy() або process.exit().

9. Спрощена візуалізація повного циклу

javascript
┌────────────────────────────────────┐ timers (setTimeout, setInterval)├────────────────────────────────────┤ │ pending callbacks (I/O)├────────────────────────────────────┤ │ idle, prepare │ ├────────────────────────────────────┤ poll (очікування I/O подій)├────────────────────────────────────┤ check (setImmediate)├────────────────────────────────────┤ │ close callbacks (закриття)└────────────────────────────────────┘ ▲ │ │ ▼ microtasks (Promises, nextTick)

10. Резюме

ФазаЩо робитьПриклади
timersВиконує callback-и від setTimeout / setIntervalsetTimeout(cb, 1000)
pending callbacksСистемні callback-и від I/O операційTCP, DNS
idle, prepareВнутрішні службові етапи libuv-
pollЧекає I/O, обробляє їхні callback-иfs.readFile, net, http
checkВиконує setImmediatesetImmediate(cb)
close callbacksЗакриття ресурсівsocket.on('close')
microtasksМіжфазові задачіPromise.then(), process.nextTick()

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.