При работе с динамическими интерфейсами в JavaScript, особенно при
использовании библиотек вроде Masonry, часто возникает
необходимость контролировать частоту выполнения обработчиков событий.
Это особенно важно для событий, которые вызываются очень часто, например
scroll, resize или mousemove. Без
контроля частоты вызовов обработчики могут перегружать браузер, приводя
к падению производительности и задержкам в рендеринге сетки Masonry.
Throttling и Debouncing — два фундаментальных подхода для оптимизации таких событий.
Debouncing гарантирует, что функция будет выполнена только после того, как событие перестанет происходить в течение заданного интервала времени.
resize.function debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
// Применение с Masonry
const grid = document.querySelector('.grid');
const msnry = new Masonry(grid, {
itemSelector: '.grid-item',
columnWidth: 200,
gutter: 10
});
window.addEventListener('resize', debounce(() => {
msnry.layout();
}, 250));
Ключевой момент: debounce полезен,
когда нужно выполнить действие только один раз после завершения
серии событий, например пересчет сетки после завершения
изменения размера окна.
Throttling ограничивает частоту вызова функции, гарантируя, что она будет выполняться не чаще, чем раз в указанный интервал времени.
scroll.function throttle(func, limit) {
let lastFunc;
let lastRan;
return function(...args) {
const context = this;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
// Применение с Masonry
window.addEventListener('scroll', throttle(() => {
msnry.layout();
}, 200));
Ключевой момент: throttle идеально
подходит для регулярного выполнения функции во время длительных
событий, например прокрутки страницы или анимации.
| Особенность | Debounce | Throttle |
|---|---|---|
| Выполнение функции | Только после прекращения серии событий | Периодически, с фиксированным интервалом |
| Частые события | Отлично для resize, input |
Отлично для scroll, mousemove |
| Контроль нагрузки | Минимизирует вызовы до одного | Позволяет регулярное выполнение |
| Использование с Masonry | Перерасчет сетки после изменения размера | Поддержание актуального расположения при скролле |
В контексте Masonry правильное использование debounce и throttle повышает производительность:
Debounce при изменении размера окна После окончания изменения размеров, Masonry пересчитывает позиции элементов, что предотвращает множественные лишние расчеты.
Throttle при прокрутке или динамической подгрузке
контента Если добавляются новые элементы при прокрутке
страницы, throttle обеспечивает плавное обновление сетки
без резких подтормаживаний.
const grid = document.querySelector('.grid');
const msnry = new Masonry(grid, {
itemSelector: '.grid-item',
columnWidth: 200,
gutter: 10
});
// Перерасчет при изменении окна с debounce
window.addEventListener('resize', debounce(() => {
msnry.layout();
}, 300));
// Подгрузка новых элементов при scroll с throttle
window.addEventListener('scroll', throttle(() => {
if (window.scrollY + window.innerHeight >= document.body.scrollHeight - 100) {
loadMoreItems().then(newItems => {
grid.append(...newItems);
msnry.appended(newItems);
});
}
}, 200));
scroll,
mousemove) лучше использовать throttle,
чтобы избежать перегрузки браузера.resize, input), лучше использовать
debounce.apply или call, чтобы не потерять доступ к
this в классах или объектах.Эффективное применение throttle и debounce позволяет Masonry поддерживать стабильную и плавную работу сетки даже при динамических изменениях и большом количестве элементов.