Події в JavaScript: як працює Event Loop
JavaScript, Веб-розробка ·JavaScript — це мова програмування з однопотоковою природою, але при цьому вона вміє обробляти асинхронні операції. Це можливо завдяки Event Loop — механізму, який дозволяє JavaScript виконувати код без блокування основного потоку. У цьому дописі розглянемо, як саме працює Event Loop, чому він важливий і як правильно використовувати його особливості.
Основи роботи Event Loop
В основі роботи Event Loop лежать три основні складові:
- Call Stack (стек викликів) — місце, де виконуються синхронні функції.
- Task Queue (черга завдань) — список колбеків, які чекають своєї черги для виконання.
- Microtask Queue (черга мікрозавдань) — черга для Promise та інших мікрозавдань.
Розглянемо приклад:
console.log("Початок");
setTimeout(() => {
console.log("setTimeout");
}, 0);
Promise.resolve().then(() => {
console.log("Promise");
});
console.log("Кінець");
Очікуваний порядок виконання:
console.log("Початок")
— виводиться одразу.setTimeout
відкладає виконання колбека в Task Queue.Promise.resolve().then(...)
додає колбек у Microtask Queue.console.log("Кінець")
— виводиться одразу.- Після завершення синхронного коду Event Loop перевіряє Microtask Queue — виконується
console.log("Promise")
. - Лише після цього виконується колбек з Task Queue —
console.log("setTimeout")
.
Результат у консолі буде:
Початок
Кінець
Promise
setTimeout
Чому setTimeout(..., 0)
не виконується миттєво?
setTimeout(..., 0)
не означає, що функція виконається одразу. Він додає колбек у Task Queue, який обробляється лише після виконання всіх мікрозавдань.
Приклад, де це добре видно:
setTimeout(() => console.log("setTimeout"), 0);
for (let i = 0; i < 1e9; i++) {} // Блокуємо основний потік
console.log("Кінець циклу");
Тут setTimeout
затримується, поки цикл не завершиться, навіть якщо стоїть 0
мілісекунд.
Використання queueMicrotask
Якщо потрібно виконати код раніше, ніж setTimeout
, можна скористатися queueMicrotask
:
queueMicrotask(() => console.log("Мікрозавдання"));
console.log("Основний код");
Результат:
Основний код
Мікрозавдання