Debounce и throttle — это техники контроля частоты вызова функций при работе с событиями, особенно полезные при обработке событий прокрутки, ресайза окна, ввода текста или движения мыши. Они помогают оптимизировать производительность и предотвращают перегрузку браузера из-за чрезмерного количества вызовов.
Debounce ограничивает выполнение функции, задерживая её вызов до тех пор, пока не прекратятся последовательные события на заданный интервал времени. Это значит, что функция будет выполнена только после того, как событие больше не повторялось.
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
Пояснение к коду:
timeoutId хранит идентификатор таймера.clearTimeout сбрасывает предыдущий таймер при каждом
новом вызове.setTimeout выполняет функцию после указанной задержки,
если не появится новый вызов.window.addEventListener('resize', debounce(() => {
console.log('Размер окна изменён');
}, 300));
Здесь функция будет вызвана только один раз через 300 мс после того, как пользователь перестанет изменять размер окна.
Throttle ограничивает частоту вызова функции, гарантируя её выполнение не чаще одного раза за заданный интервал времени, независимо от того, сколько раз событие происходит.
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));
}
};
}
Пояснение к коду:
lastRan хранит время последнего вызова функции.lastFunc используется для отложенного вызова, если
событие произошло слишком часто.limit миллисекунд.window.addEventListener('scroll', throttle(() => {
console.log('Прокрутка страницы');
}, 200));
Функция будет выполняться максимум один раз каждые 200 мс, даже если событие scroll срабатывает чаще.
| Характеристика | Debounce | Throttle |
|---|---|---|
| Поведение при частых вызовах | Выполняется только после окончания серии событий | Выполняется регулярно, но не чаще заданного интервала |
| Идеально подходит для | Поисковых форм, автосохранения, ресайза окна | Прокрутки, анимаций, отслеживания позиции мыши |
| Основная цель | Сокращение количества вызовов функции после активного события | Ограничение частоты вызова функции |
При работе с GSAP для анимаций часто возникают ситуации, когда события браузера могут запускать анимации слишком часто:
const updateLayout = () => {
gsap.to('.box', { x: window.innerWidth / 2, duration: 0.5 });
};
window.addEventListener('resize', debounce(updateLayout, 250));
const animateOnScroll = () => {
gsap.to('.section', {
y: window.scrollY / 2,
duration: 0.3
});
};
window.addEventListener('scroll', throttle(animateOnScroll, 100));
function debounceImmediate(func, delay, immediate = false) {
let timeout;
return function(...args) {
const context = this;
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(() => {
timeout = null;
if (!immediate) func.apply(context, args);
}, delay);
if (callNow) func.apply(context, args);
};
}
function throttleAdvanced(func, limit, options = { leading: true, trailing: true }) {
let lastCall = 0;
let timeout;
return function(...args) {
const now = Date.now();
const context = this;
const remaining = limit - (now - lastCall);
if (remaining <= 0) {
clearTimeout(timeout);
lastCall = now;
if (options.leading) func.apply(context, args);
} else if (options.trailing) {
clearTimeout(timeout);
timeout = setTimeout(() => {
lastCall = options.leading ? Date.now() : 0;
func.apply(context, args);
}, remaining);
}
};
}
Эти подходы дают полный контроль над частотой вызовов функций, что критично при сложных анимациях и интерактивных интерфейсах.
.kill(),
.pause() и .resume() для управления анимациями
при слишком частых событиях.Эти методы позволяют писать плавные и отзывчивые интерфейсы, минимизировать нагрузку на браузер и обеспечивать синхронизацию событий с анимацией.