Debounce и Throttle
Оба паттерна ограничивают частоту вызовов функции, но по-разному.
Debounce
Вызывает функцию спустя N миллисекунд после последнего вызова. Если новые вызовы приходят раньше таймаута - таймер сбрасывается.
function debounce(fn, delay) {
let timer
return function(...args) {
clearTimeout(timer)
timer = setTimeout(() => fn.apply(this, args), delay)
}
}
// Поиск запрашивается только после паузы в 300мс
const search = debounce((query) => fetchResults(query), 300)
input.addEventListener("input", (e) => search(e.target.value))
Когда использовать: поиск по мере ввода, автосохранение, resize окна.
Throttle
Вызывает функцию не чаще раза в N миллисекунд. Промежуточные вызовы игнорируются.
function throttle(fn, limit) {
let inThrottle = false
return function(...args) {
if (!inThrottle) {
fn.apply(this, args)
inThrottle = true
setTimeout(() => { inThrottle = false }, limit)
}
}
}
// scroll-обработчик не чаще раза в 100мс
window.addEventListener("scroll", throttle(updatePosition, 100))
Когда использовать: scroll-обработчики, mousemove, анимации, rate limiting API.
Разница наглядно
Один и тот же поток частых событий, но реакция разная: debounce ждёт тишины и срабатывает один раз в конце, throttle срабатывает регулярно прямо во время потока.
- Debounce — пока события идут подряд, таймер сбрасывается; функция вызовется только один раз, когда поток прекратится на заданное время.
- Throttle — функция вызывается сразу и затем не чаще раза в интервал, сколько бы событий ни пришло между ними.