← Назад к вопросам
На каком этапе относительно микро и макротасок находится задача по рендерингу?
2.3 Middle🔥 191 комментариев
#Браузер и сетевые технологии#Оптимизация и производительность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Рендеринг в Event Loop
Рендеринг находится в очень специфической позиции в Event Loop. Правильное понимание этого критично для оптимизации производительности браузера.
Порядок выполнения Event Loop
// 1. Выполнить макротаску (например, setTimeout)
console.log("1. Синхронный код");
// 2. Выполнить ВСЕ микротаски (Promise, queueMicrotask)
Promise.resolve().then(() => console.log("2. Микротаска"));
// 3. РЕНДЕРИНГ браузером (если нужен)
// [ЗДЕСЬ ПРОИСХОДИТ ОТРИСОВКА]
// 4. setTimeout и другие макротаски
setTimeout(() => console.log("4. Макротаска"), 0);
Полная схема Event Loop
1. Выполнить одну макротаску (setTimeout, setInterval)
2. Выполнить ВСЕ доступные микротаски (Promise)
3. requestAnimationFrame callbacks
4. РЕНДЕРИНГ (обновить отображение)
5. requestIdleCallback (если есть свободное время)
6. Вернуться к шагу 1
Ключевой момент: Рендеринг МЕЖДУ макротасками
const box = document.querySelector(".box");
// Первая макротаска
setTimeout(() => {
box.style.left = "0px";
}, 0);
// РЕНДЕРИНГ ПРОИСХОДИТ ЗДЕСЬ! Браузер рисует позицию 0px
// Вторая макротаска
setTimeout(() => {
box.style.left = "100px";
}, 0);
// РЕНДЕРИНГ ПРОИСХОДИТ ЗДЕСЬ! Браузер рисует позицию 100px
Микротаски выполняются ДО рендеринга
const div = document.querySelector("div");
// Изменяем DOM
div.style.backgroundColor = "red";
// Микротаска выполнится ДО рендеринга
Promise.resolve().then(() => {
console.log("Это выполнится ДО того, как браузер перерисует");
// Можно ещё изменить DOM
div.style.borderColor = "blue";
});
// ЗАТЕМ ПРОИСХОДИТ РЕНДЕРИНГ
// Браузер видит оба изменения (background и border) за одну отрисовку
requestAnimationFrame
Это функция, которая вызывает callback прямо ПЕРЕД рендерингом.
// rAF выполняется ДО рендеринга, оптимально для анимаций
requestAnimationFrame((timestamp) => {
box.style.transform = "translateX(10px)";
});
// setTimeout выполняется ПОСЛЕ рендеринга
setTimeout(() => {
box.style.transform = "translateX(10px)";
}, 0);
Практический пример
console.log("Start");
setTimeout(() => {
console.log("Макротаска 1");
}, 0);
Promise.resolve()
.then(() => console.log("Микротаска 1"))
.then(() => console.log("Микротаска 2"));
setTimeout(() => {
console.log("Макротаска 2");
}, 0);
console.log("End");
// Вывод:
// Start
// End
// Микротаска 1 все микротаски выполнены
// Микротаска 2 раньше рендеринга
// [РЕНДЕРИНГ]
// Макротаска 1 Макротаска
// [РЕНДЕРИНГ]
// Макротаска 2 Макротаска
// [РЕНДЕРИНГ]
Батчинг изменений DOM
// Хорошо - один рендеринг на все изменения
div1.style.color = "red";
div2.style.color = "blue";
div3.style.color = "green";
// Один рендеринг покроет все три изменения
// Плохо - много рендерингов
setTimeout(() => { div1.style.color = "red"; }, 0);
setTimeout(() => { div2.style.color = "blue"; }, 0);
setTimeout(() => { div3.style.color = "green"; }, 0);
// Три разных рендеринга!
Вывод
Рендеринг находится МЕЖДУ макротасками и ПОСЛЕ микротасок:
- Микротаски > Рендеринг > Макротаска > Микротаски > Рендеринг
- Это позволяет батчировать изменения DOM
- requestAnimationFrame синхронизирован с рендерингом
- setTimeout и setInterval разделяют рендеринг между вызовами