Встречается на 66% собеседований по JavaScript

Расскажи про event loop

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

Как это работает

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

  1. Call Stack (стек вызовов) — хранит текущий контекст выполнения. Когда вызывается функция, она добавляется в стек; когда функция завершается, она удаляется из стека.
  2. Callback Queue (очередь обратных вызовов) — сюда попадают колбэки от асинхронных операций после их завершения.
  3. Event Loop — постоянно проверяет, пуст ли стек вызовов. Если стек пуст, он берёт первый колбэк из очереди и помещает его в стек для выполнения.

Этот процесс повторяется бесконечно, что и создаёт цикл событий.

Пример

Рассмотрим простой пример с setTimeout:

javascript
console.log('Первое сообщение');
setTimeout(() => {
    console.log('Сообщение из setTimeout');
}, 0);
console.log('Второе сообщение');

Несмотря на задержку в 0 миллисекунд, вывод будет таким:

text
Первое сообщение
Второе сообщение
Сообщение из setTimeout

Почему? Потому что setTimeout помещает свой колбэк в очередь обратных вызовов, а не выполняет его сразу. Event Loop сначала завершает выполнение всего синхронного кода в стеке (включая console.log('Второе сообщение')), и только когда стек становится пустым, колбэк из очереди попадает в стек и выполняется.

Подводные камни

  • Очередь микрозадач: В дополнение к обычной очереди обратных вызовов существует очередь микрозадач (например, промисы). Микрозадачи имеют приоритет над обычными колбэками: Event Loop обрабатывает все микрозадачи из очереди перед тем, как взять следующую задачу из callback queue. Это может привести к неожиданному порядку выполнения, если не учитывать этот нюанс.
  • Блокировка стека: Если в стеке вызовов выполняется тяжёлая синхронная операция (например, бесконечный цикл), Event Loop не сможет обработать очередь, и приложение «зависнет». Поэтому важно не перегружать основной поток.
  • setTimeout с задержкой 0 не гарантирует мгновенное выполнение — он лишь ставит колбэк в очередь, и время выполнения зависит от текущей загрузки стека.

Когда использовать

Понимание Event Loop необходимо при работе с асинхронным кодом: обработке событий, таймерах, промисах, async/await, запросах к серверу. Это помогает избежать ошибок, связанных с порядком выполнения, и писать эффективный неблокирующий код.

Коротко

  • Event Loop позволяет JavaScript выполнять асинхронные операции в однопоточном режиме, не блокируя основной поток.
  • Основные компоненты: стек вызовов, очередь обратных вызовов и сам цикл, который переносит колбэки из очереди в стек.
  • Порядок выполнения: сначала весь синхронный код, затем колбэки из очереди; микрозадачи (промисы) выполняются раньше обычных колбэков.
  • Избегайте тяжёлых синхронных операций в основном потоке, чтобы не блокировать Event Loop.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы