← Назад к вопросам

Как работает Event Loop на сайте?

2.0 Middle🔥 221 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Event Loop - сердце асинхронного JavaScript

Event Loop (цикл событий) - это механизм, который позволяет JavaScript обрабатывать асинхронные операции несмотря на то, что язык однопоточный. Это фундаментальная концепция, которая объясняет, как браузер управляет выполнением кода, обработкой событий и рендерингом.

Основные компоненты

Event Loop состоит из нескольких основных компонентов:

  1. Call Stack - стек вызовов, где хранится текущий код
  2. Web APIs - API браузера (setTimeout, fetch, DOM события)
  3. Callback Queue (Task Queue) - очередь обратных вызовов
  4. Microtask Queue - очередь микротасков (Promise, queueMicrotask)
  5. Render Queue - очередь операций рендеринга

Как работает Event Loop

Event Loop постоянно проверяет, пуст ли Call Stack. Если он пуст, браузер переходит к следующему этапу обработки очередей.

Порядок приоритетов

  1. Call Stack - выполнить синхронный код
  2. Microtask Queue - выполнить все микротаски (Promises, queueMicrotask)
  3. Render - если нужно, перерисовать страницу
  4. Callback Queue (Macrotasks) - выполнить одну макротаску (setTimeout, setInterval)

Этот цикл повторяется бесконечно.

Пример выполнения

console.log('1'); // Синхронный код - Call Stack

setTimeout(() => {
  console.log('2'); // Macrotask - Callback Queue
}, 0);

Promise.resolve().then(() => {
  console.log('3'); // Microtask - Microtask Queue
});

console.log('4'); // Синхронный код - Call Stack

// Результат:
// 1
// 4
// 3
// 2

Подробное объяснение примера

  1. console.log('1') выполняется синхронно - Call Stack
  2. setTimeout отправляется в Web API, затем callback попадает в Callback Queue
  3. Promise.then() попадает в Microtask Queue
  4. console.log('4') выполняется синхронно - Call Stack
  5. Call Stack пуст, Event Loop проверяет Microtask Queue
  6. Выполняется console.log('3')
  7. Microtask Queue пуст, браузер может перерисовать (Render)
  8. Event Loop берет одну задачу из Callback Queue
  9. Выполняется console.log('2')

Макротаски vs Микротаски

Макротаски (Tasks)

  • setTimeout
  • setInterval
  • setImmediate (Node.js)
  • I/O операции
  • UI рендеринг

Микротаски (Microtasks)

  • Promise.then/catch/finally
  • queueMicrotask
  • MutationObserver
  • process.nextTick (Node.js)

Сложный пример

console.log('start');

setTimeout(() => {
  console.log('setTimeout 1');
  Promise.resolve().then(() => console.log('promise in setTimeout'));
}, 0);

Promise.resolve()
  .then(() => {
    console.log('promise 1');
    setTimeout(() => console.log('setTimeout in promise'), 0);
  })
  .then(() => console.log('promise 2'));

console.log('end');

// Результат:
// start
// end
// promise 1
// promise 2
// setTimeout 1
// promise in setTimeout
// setTimeout in promise

Визуализация процесса

┌─────────────────────────────┐
│    Call Stack (пусто?)      │
└─────────────────────────────┘
          |
        Нет? -> Выполнить синхронный код
          |
        Да? Перейти ниже
          |
┌─────────────────────────────┐
│   Microtask Queue (пусто?)  │
└─────────────────────────────┘
          |
        Нет? -> Выполнить все микротаски
          |
        Да? Перейти ниже
          |
┌─────────────────────────────┐
│  Нужен рендеринг? Перерисовать │
└─────────────────────────────┘
          |
┌─────────────────────────────┐
│  Callback Queue (пусто?)    │
└─────────────────────────────┘
          |
        Нет? -> Выполнить одну макротаску
          |
        Да? Повторить цикл

Практическое значение

Понимание Event Loop критично для:

  • Оптимизации производительности
  • Предотвращения "зависаний" UI
  • Правильной работы с асинхронным кодом
  • Отладки race conditions

Рекомендации

  1. Тяжелые операции отправляйте в Web Workers для не блокирования Event Loop
  2. Избегайте глубокой вложенности Promise
  3. Используйте async/await для более читаемого кода
  4. Помните, что setTimeout(..., 0) не означает немедленное выполнение
  5. Используйте requestAnimationFrame для анимаций - он синхронизирован с рендерингом

Итог

Event Loop - это механизм, который позволяет браузеру обрабатывать множество операций, хотя JavaScript выполняется в одном потоке. Правильное понимание порядка выполнения (синхронный код -> микротаски -> рендеринг -> макротаски) необходимо для написания эффективного кода и избежания проблем с производительностью.