Из каких этапов состоит событийный цикл JavaScript
Что проверяют
Можете ли вы описать порядок выполнения по шагам и знаете ли, где в этом порядке находится отрисовка.
Как отвечать
Опишите цикл как повторяющийся круг:
- стек вызовов выполняет синхронный код. Пока он не пуст, ничего другого не происходит;
- когда стек опустел, движок разгребает очередь микрозадач целиком: колбэки промисов,
queueMicrotask,MutationObserver. Микрозадача, породившая новую микрозадачу, обработается в этом же круге; - затем берётся одна макрозадача: таймер, событие ввода, сетевой колбэк, и снова разгребаются микрозадачи;
- перед отрисовкой кадра выполняются колбэки
requestAnimationFrame, затем браузер считает стили, раскладку и рисует; - в свободное время могут выполниться
requestIdleCallback.
Ключевое правило порядка: микрозадачи всегда раньше следующей макрозадачи, и именно поэтому промис с нулевой задержкой опережает setTimeout(fn, 0).
setTimeout(() => console.log("макро"), 0);
Promise.resolve().then(() => console.log("микро"));
console.log("синхронно");
// синхронно, микро, макроПрактические следствия стоит назвать: бесконечная цепочка микрозадач блокирует отрисовку намертво, потому что до макрозадач и рендера очередь просто не доходит; тяжёлое вычисление в обработчике задерживает кадр, поэтому его дробят или уносят в Worker; анимации привязывают к requestAnimationFrame, а не к таймеру.
Полезно добавить, что в Node.js цикл устроен иначе: там есть фазы (таймеры, ожидание ввода-вывода, проверка), setImmediate относится к фазе проверки, а process.nextTick выполняется даже раньше промисов.
Где спотыкаются
Считают, что setTimeout(fn, 0) выполнится немедленно.
Не знают, что очередь микрозадач разгребается целиком, и объясняют порядок вывода случайностью.
Путают браузерный цикл с моделью Node.js.