Skip to main content

Детально про Event loop

Що таке Event Loop?

Event Loop - механізм, який організовує виконання JS-коду в однопотоковому середовищі: бере задачі, запускає їх, після кожної задачі прогонює мікрозадачі, за потреби дає браузеру відрендерити, потім бере наступну задачу. Це "диригент" між стеком викликів, чергами задач і відмальовуванням.

Спрощено (браузер):

javascript
while (true) { взяти одну macrotask → виконати поки є microtask → виконувати по одній (FIFO) якщо можна → виконати rAF/рендер }

Що робить call stack?

Call stack (стек викликів) - це LIFO-структура, де виконуються функції "тут і зараз".

  • Викликали функцію - вона пушиться в стек.
  • Функція завершилася - поп зі стека.
  • Поки стек не порожній, жодні колбеки з черг виконуватися не можуть.

Що робить microtask queue?

Microtask queue - черга "термінових" коротких задач, які виконуються одразу після поточної задачі (після спорожнення стека) і до наступної macrotask/рендера.

  • Приклади джерел: Promise.then/catch/finally, queueMicrotask, MutationObserver (браузер), process.nextTick (Node.js: окрема надмікрочерга).
  • Важливо: усі мікрозадачі виконуються поспіль. Довгий ланцюжок мікрозадач може заблокувати рендер (starvation).

Що робить macrotask queue?

Macrotask queue - черга "звичайних" подій/задач: таймери, I/O, UI-події.

  • Приклади (браузер): setTimeout, setInterval, MessageChannel, користувацькі події, мережеві колбеки.
  • Приклади (Node.js): setTimeout/setInterval (timers), setImmediate (check), I/O callbacks та ін.
  • Event Loop бере одну macrotask, виконує її повністю, потім спорожнює microtask queue.

Чим microtasks відрізняються від macrotasks?

  • Момент виконання: microtasks - одразу після поточної задачі і до рендера; macrotasks - по одній за "тик" циклу.
  • Пріоритет: microtasks мають вищий пріоритет (вони "вклинюються" між macrotasks).
  • Типові джерела: microtasks - Promise/queueMicrotask; macrotasks - setTimeout, події UI/I/O.
  • Ризик: нескінченні microtasks можуть затримати відмальовування й відгук інтерфейсу.

Що робить queueMicrotask()?

Планує колбек у microtask queue:

  • Виконається після поточного стека, до наступної macrotask і до рендера.
  • По суті - "як Promise.then, але без створення зайвого проміса".
javascript
console.log('A'); queueMicrotask(() => console.log('microtask-1')); Promise.resolve().then(() => console.log('microtask-2')); setTimeout(() => console.log('macrotask (timeout)'), 0); console.log('B'); // Порядок виводу: // A // B // microtask-1 // microtask-2 // macrotask (timeout)

Чому так? Спочатку виконується скрипт (одна macrotask): друкуємо A, ставимо мікрозадачі, ставимо макрозадачу, друкуємо B. Потім усі мікрозадачі (queueMicrotask/Promise), і лише потім - setTimeout.


Ще кілька практичних заміток

  • У браузері рендер зазвичай відбувається після спорожнення microtask queue і між macrotasks. Довгі мікрозадачі = "фризи".
  • У Node.js є фази циклу (timers → pending callbacks → poll → check → close). Мікрозадачі виконуються після кожного колбека і наприкінці тіку. process.nextTick виконується навіть раніше за звичайні microtasks - не зловживай цим.
  • requestAnimationFrame - не micro/macrotask; це кадр відмальовування, який настає після мікрозадач і перед рендером.

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

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

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