При работе с интерфейсами на JavaScript нередко возникает
необходимость контролировать частоту вызова обработчиков событий. Это
особенно актуально для событий, которые срабатывают многократно за
короткий промежуток времени: scroll, resize,
mousemove, input и подобных. Без контроля
частоты вызовов нагрузка на браузер и производительность страницы может
сильно возрасти. Дебаунсинг (debounce) и троттлинг (throttle) позволяют
решать эту задачу.
Дебаунсинг — это техника, при которой функция вызывается только один раз после того, как событие перестало срабатывать в течение заданного времени. Другими словами, обработчик «откладывает» выполнение до момента, когда поток событий временно прекращается.
function debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
fn — функция, выполнение которой необходимо
контролировать.delay — задержка в миллисекундах.timeoutId хранит идентификатор таймера, чтобы при
повторном срабатывании события предыдущий таймер сбрасывался.Сценарий применения: поиск по мере ввода текста. Без дебаунса каждый ввод символа запускает запрос к серверу, создавая лишнюю нагрузку. С дебаунсом запрос отправляется только после паузы, например, 300 мс.
const input = document.querySelector('#search');
input.addEventListener('input', debounce((event) => {
console.log('Запрос к серверу для', event.target.value);
}, 300));
Троттлинг ограничивает максимальную частоту вызова функции, независимо от того, как часто событие срабатывает. В отличие от дебаунса, троттлинг позволяет функции выполняться через фиксированные интервалы, игнорируя промежуточные события.
function throttle(fn, interval) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= interval) {
lastTime = now;
fn.apply(this, args);
}
};
}
interval задаёт минимальный интервал между
вызовами.lastTime фиксирует время последнего срабатывания
функции.Сценарий применения: прокрутка страницы. Например,
обновление координат элементов на экране при scroll не
должно выполняться на каждый пиксель движения, а с частотой один раз в
100 мс.
window.addEventListener('scroll', throttle(() => {
console.log('Обновление позиции элементов');
}, 100));
| Характеристика | Дебаунсинг | Троттлинг |
|---|---|---|
| Вызов функции | После прекращения потока событий | Через фиксированные интервалы |
| Идеальный случай | Поиск, ввод текста, resize | scroll, mousemove, анимации |
| Частота вызова | Один раз после «паузы» | Постоянная с заданной частотой |
| Поведение при частых событиях | Отложенный вызов после последнего события | Ограничение количества вызовов |
При работе с библиотекой SVG.js часто возникают ситуации, когда нужно
анимировать или перерисовывать элементы в ответ на пользовательские
действия. Например, масштабирование или перетаскивание сложной графики
может генерировать сотни событий mousemove в секунду.
Использование троттлинга и дебаунса снижает нагрузку на DOM и
обеспечивает плавность интерфейса.
const draw = SVG().addTo('body').size(500, 500);
const rect = draw.rect(100, 100).fill('blue');
function moveRect(event) {
rect.move(event.clientX - 50, event.clientY - 50);
}
document.addEventListener('mousemove', throttle(moveRect, 16)); // ~60 FPS
В этом примере throttle ограничивает обновление позиции
прямоугольника до 60 кадров в секунду, что позволяет сохранить плавность
перемещения без перегрузки браузера.
animate,
during) и не вызывать перерисовку слишком часто, иначе
анимация будет «рывковой».Выбор метода зависит от цели события:
Не использовать одновременно троттлинг и дебаунс без необходимости, это усложняет логику и может привести к задержкам.
Тестировать производительность при работе с SVG-элементами: слишком частые перерисовки сильно снижают FPS, особенно на мобильных устройствах.
Учитывать контекст this: в
функциях-декораторах (throttle, debounce)
нужно использовать fn.apply(this, args), чтобы сохранить
привязку к объекту.
Эти техники обеспечивают контроль над частотой событий и плавность интерактивной работы интерфейсов с графикой, особенно при динамическом изменении элементов SVG в реальном времени.