Как Event Loop работает с рендерингом?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Event Loop и рендеринг
Рендеринг в браузере привязан к Event Loop, но не является частью JavaScript. Это критически важное понимание для оптимизации производительности фронтенд-приложений.
Цикл Event Loop с рендерингом
Полный цикл выглядит так:
- Выполнить один Macrotask (или несколько Microtasks)
- Выполнить ВСЕ Microtasks
- Проверить, нужен ли рендеринг
- Если нужен:
- Запустить requestAnimationFrame callbacks
- Обновить DOM (layout, paint, composite)
- Если остаток времени до следующего кадра:
- Выполнить следующий Macrotask
- Повторить
Временная шкала кадра (Frame Time)
В современных браузерах целевая частота кадров 60fps, то есть один кадр должен быть готов за ~16.67мс.
Идеальный сценарий:
- 0ms: Macrotask (выполняется код)
- 6ms: Microtasks (промисы, мутации)
- 8ms: rAF callbacks (анимации)
- 10ms: Рендеринг (layout, paint)
- 16.67ms: Кадр отправлен на экран
Когда срабатывает рендеринг
Браузер проверяет рендеринг только после Macrotask + Microtasks. Если код достаточно быстрый, рендеринг может не произойти в текущем цикле.
setTimeout(() => {
element.style.backgroundColor = 'red';
}, 0);
for (let i = 0; i < 1000; i++) {
element.style.transform = `translateX(${i}px)`;
}
RequestAnimationFrame vs setTimeout
requestAnimationFrame (rAF) синхронизируется с рендерингом браузера:
function animate() {
element.style.left = x + 'px';
requestAnimationFrame(animate);
}
animate();
rAF вызывается перед рендерингом, a setTimeout — это Macrotask, может быть выполнен раньше или позже.
Практический пример: Force Layout
for (let i = 0; i < 100; i++) {
element.style.width = (i * 10) + 'px';
console.log(element.offsetWidth);
}
Paint/Layout/Composite
Браузер выполняет три этапа рендеринга:
- Layout (Reflow) — пересчёт размеров и позиций
- Paint (Repaint) — отрисовка пикселей
- Composite — объединение слоёв (самый быстрый)
element.style.transform = 'translateX(100px)';
element.style.left = '100px';
Ключевой вывод
Рендеринг — это независимый процесс браузера, синхронизированный с его частотой обновления (~60fps). Код JavaScript блокирует рендеринг, пока выполняется, поэтому долгие операции нужно разбивать на части, а для анимаций использовать requestAnimationFrame вместо setTimeout.