Event Loop браузера
↑ 2.1 JavaScript: продвинутый · ← Предыдущая · → Следующая
Зачем это на собесе
Как event loop связан с рендерингом:
requestAnimationFrame, layout thrashing, «подвисания» интерфейса.
Объяснение
Один цикл в браузере (упрощённо):
flowchart LR T[Макрозадача] --> M[Все микрозадачи] M --> R{Пора рендерить? ~16 мс} R -- да --> RAF[requestAnimationFrame коллбэки] --> S[Style + Layout] --> P[Paint] --> C[Composite] R -- нет --> N[Следующая макрозадача] C --> N
| API | Когда выполняется |
|---|---|
setTimeout | макрозадача после задержки |
requestAnimationFrame | перед следующей отрисовкой (~60 Гц) |
requestIdleCallback | в простое, для низкоприоритетной работы |
queueMicrotask / Promise | до рендера, сразу после задачи |
scheduler.postTask, scheduler.yield | приоритетные задачи, уступка потоку |
| События ввода | макрозадачи с высоким приоритетом |
Бюджет кадра — ~16 мс: JS, style, layout, paint должны уложиться, иначе пропуски кадров (jank). INP измеряет отзывчивость на ввод.
Layout thrashing: чередование чтения (offsetHeight, getBoundingClientRect) и записи стилей в цикле заставляет браузер пересчитывать layout многократно.
// Плохо
for (const el of els) { el.style.width = el.offsetWidth + 10 + "px"; } // read/write чередуются
// Хорошо: сначала читаем всё, затем пишем
const widths = els.map(el => el.offsetWidth);
els.forEach((el, i) => el.style.width = widths[i] + 10 + "px");
requestAnimationFrame(() => { /* визуальные изменения синхронно с кадром */ });Выносите тяжёлое: Web Workers, OffscreenCanvas, разбиение на чанки, content-visibility: auto, виртуализация списков.
Нюансы и подводные камни
- Фоновые вкладки: таймеры и
rAFзамедляются/останавливаются. - Долгие задачи (> 50 мс) — «long tasks», ухудшают INP.
alert/confirmблокируют цикл.rAFвызывается перед paint, но не гарантирует рендер каждого кадра.
Практика
- Найдите long tasks в Performance и разбейте функцию на части.
- Устраните layout thrashing в примере.
- Реализуйте плавную анимацию через
requestAnimationFrame.
Вопросы с ответами
Когда браузер рендерит страницу?
Между макрозадачами, после выполнения микрозадач, обычно ~60 раз в секунду, если есть что рисовать.
Что такое layout thrashing?
Повторные принудительные пересчёты layout из-за чередования чтения геометрии и записи стилей.