З яких фаз складається Event Loop?
1. Що таке "фаза" Event Loop
Event Loop у Node.js реалізовано через бібліотеку libuv. Кожна ітерація (цикл) Event Loop ділиться на фази - логічні етапи, на яких виконуються різні типи callback-ів.
Одна ітерація Event Loop називається tick. Після виконання всіх фаз цикл починається знову (поки є задачі).
2. Основні фази Event Loop
| № | Фаза | Що робить | Приклади callback-ів |
|---|---|---|---|
| 1 | timers | Виконує callback-и від setTimeout() і setInterval() | setTimeout(cb, 0) |
| 2 | pending callbacks | Виконує деякі відкладені системні callback-и (помилки I/O, TCP тощо) | Помилки сокетів, TCP.onconnection |
| 3 | idle, prepare | Внутрішні фази libuv (не використовуються напряму в JS) | - |
| 4 | poll | Основна фаза очікування I/O. Виконує готові I/O callback-и або чекає нових подій | fs.readFile(), мережеві події |
| 5 | check | Виконує callback-и від setImmediate() | setImmediate(cb) |
| 6 | close 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.
Пріоритет:
process.nextTick()- виконується перед microtasks.- Microtasks (
Promise.then,queueMicrotask). - Далі - перехід до наступної фази 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Чому:
nextTickіpromise→ черга microtask;- потім фаза
timers(timeout); - потім фаза
check(immediate).
7. Особливості фаз poll і check
Фаза poll:
- Основна фаза Event Loop.
- Саме тут Node.js чекає нових I/O подій.
- Якщо черга порожня:
- і є таймери → Event Loop перейде у фазу
timers; - якщо немає → Event Loop засне, чекаючи I/O.
- і є таймери → Event Loop перейде у фазу
Фаза 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 / setInterval | setTimeout(cb, 1000) |
| pending callbacks | Системні callback-и від I/O операцій | TCP, DNS |
| idle, prepare | Внутрішні службові етапи libuv | - |
| poll | Чекає I/O, обробляє їхні callback-и | fs.readFile, net, http |
| check | Виконує setImmediate | setImmediate(cb) |
| close callbacks | Закриття ресурсів | socket.on('close') |
| microtasks | Міжфазові задачі | Promise.then(), process.nextTick() |
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.