← Назад к вопросам
В какой момент выполнения очереди происходит перерисовка страницы
2.0 Middle🔥 111 комментариев
#Браузер и сетевые технологии#Оптимизация и производительность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Перерисовка страницы и очередь событий
Перерисовка страницы (перестановка и отрисовка элементов) происходит после полного выполнения текущего стека вызовов и перед выполнением следующей задачи из очереди задач (macrotasks).
Фазы выполнения JavaScript
Для понимания момента перерисовки важно знать, как браузер обрабатывает код:
// Примерный порядок обработки браузером:
// 1. Выполнить весь синхронный код (стек вызовов)
// 2. Выполнить все микротаски (microtasks) - Promise, MutationObserver
// 3. ПЕРЕРИСОВАТЬ страницу (repaint + reflow)
// 4. Выполнить следующую макротаску (macrotask) из очереди
Очередь задач (Event Loop)
Macrotasks (очередь задач):
setTimeoutsetIntervalsetImmediate(Node.js)- Обработка событий (click, input и т.д.)
- Перестановка (layout, paint)
Microtasks (микротаски):
Promise.then/catch/finallyasync/await(это синтаксический сахар над Promise)MutationObserverqueueMicrotask()
Жизненный цикл одной итерации
console.log('1. Синхронный код');
setTimeout(() => {
console.log('2. Макротаска (setTimeout)');
}, 0);
Promise.resolve()
.then(() => {
console.log('3. Микротаска (Promise)');
});
console.log('4. Синхронный код 2');
// Порядок вывода:
// 1. Синхронный код
// 4. Синхронный код 2
// 3. Микротаска (Promise)
// [ПЕРЕРИСОВКА СТРАНИЦЫ]
// 2. Макротаска (setTimeout)
Когда происходит перерисовка
Перерисовка (render) не происходит после каждого изменения DOM, а выполняется:
- После выполнения всех микротасок (Promise, async/await)
- Перед выполнением следующей макротаски (setTimeout, событие)
- Примерно каждые 16.67ms (для 60 FPS монитора)
Практический пример
// Сценарий 1: Перерисовка НЕ произойдет
function updateDOM() {
const el = document.getElementById('box');
el.textContent = 'Привет 1';
el.textContent = 'Привет 2';
el.textContent = 'Привет 3';
// Браузер перемалует только последнее значение
}
// Сценарий 2: Перерисовка произойдет
function updateDOMWithRepaint() {
const el = document.getElementById('box');
el.textContent = 'Привет 1';
setTimeout(() => {
el.textContent = 'Привет 2';
}, 0);
}
// Сценарий 3: requestAnimationFrame
function updateDOMSmooth() {
const el = document.getElementById('box');
el.textContent = 'Начало';
requestAnimationFrame(() => {
el.textContent = 'Анимация';
});
}
requestAnimationFrame vs setTimeout
// setTimeout выполняется ПОСЛЕ перерисовки
setTimeout(() => {
console.log('После перерисовки');
}, 0);
// requestAnimationFrame выполняется ПЕРЕД перерисовкой
requestAnimationFrame(() => {
console.log('Перед перерисовкой');
});
// Порядок для 60 FPS:
// [Выполнить JavaScript]
// [Выполнить requestAnimationFrame]
// [ПЕРЕРИСОВКА СТРАНИЦЫ]
// [Ждем 16ms]
// [Выполнить setTimeout]
Оптимизация производительности
// Неправильно: много изменений в одном цикле
for (let i = 0; i < 1000; i++) {
document.body.style.left = i + 'px';
}
// Правильно: браузер оптимизирует
const el = document.body;
for (let i = 0; i < 1000; i++) {
el.style.left = i + 'px';
}
// Лучше всего: используем requestAnimationFrame
function animate(timestamp) {
el.style.transform = 'translateX(' + timestamp + 'px)';
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
Заключение
Перерисовка происходит между выполнением микротасок и макротасок. Это критично для оптимальных анимаций. Используйте requestAnimationFrame для синхронизации с браузером и избегайте частых изменений DOM в цикле.