Event Loop (Цикл событий)
JavaScript - однопоточный язык. Event Loop - механизм, который позволяет выполнять асинхронный код, не блокируя основной поток.
Схема
Как это работает
Event Loop - это бесконечный цикл, который следит за Call Stack. Если стек пуст, он берёт следующую задачу из очереди и отправляет её на выполнение.
Любая функция сначала попадает в Call Stack и выполняется там. Если функция асинхронная (например, setTimeout или fetch) - она уходит в Web APIs, которые работают в фоне. Когда асинхронная операция завершается, её колбэк попадает в очередь: микрозадачи (Promise.then, queueMicrotask) или макрозадачи (setTimeout, setInterval).
Event Loop проверяет: как только Call Stack пуст - сначала полностью опустошает очередь микрозадач, затем берёт одну макрозадачу, снова микрозадачи - и так по кругу.
Порядок выполнения
- Сначала выполняется весь синхронный код - последовательно, строка за строкой.
- Затем выполняются все микрозадачи (
Promise.then,queueMicrotask,MutationObserver) до полного опустошения очереди. Если во время выполнения появляется новая микрозадача, она также будет выполнена сразу. - После этого из очереди берётся одна макрозадача (
setTimeout,setInterval, события и т.д.) и выполняется. - По завершении макрозадачи снова обрабатываются все накопившиеся микрозадачи.
- Затем цикл повторяется: одна макрозадача → все микрозадачи → следующая макрозадача.
console.log("1")
setTimeout(() => console.log("2"), 0) // макрозадача
Promise.resolve().then(() => console.log("3")) // микрозадача
console.log("4")
// Вывод: 1, 4, 3, 2
Почему 3 раньше 2? - После выполнения синхронного кода (1, 4) event loop сначала очищает очередь микрозадач (Promise → 3), и только потом берёт макрозадачу (setTimeout → 2).
Блокировка потока
Длинный синхронный код блокирует всё: UI, события, таймеры.
// ❌ Заморозит браузер на ~5 секунд
const start = Date.now()
while (Date.now() - start < 5000) {}
// ✅ Разбить на части через setTimeout/requestAnimationFrame
requestAnimationFrame
Стоит между макрозадачами и рендером. Используется для анимаций - гарантирует выполнение перед следующим кадром (≈60 раз/сек).