Debounce и throttle: идея и реализация
Два приёма контроля частоты вызовов — обязательная практическая задача на собеседовании.
Debounce откладывает вызов, пока события не прекратятся. Throttle разрешает вызов не чаще раза в заданный интервал.
Зачем это нужно
Некоторые события случаются очень часто: ввод в поле, скролл, изменение размера окна. Если на каждое из них дёргать тяжёлый обработчик (запрос на сервер, перерисовку) — интерфейс начнёт тормозить. debounce и throttle ограничивают частоту вызовов.
| Приём | Поведение | Пример |
| debounce | ждёт паузу, потом один вызов | поиск по мере ввода |
| throttle | не чаще раза в N мс | обработка скролла |
Реализация debounce
Идея: при каждом вызове сбрасываем предыдущий таймер и ставим новый. Реальный вызов происходит, только когда между событиями прошла достаточная пауза. Замыкание хранит timer между вызовами.
function debounce(fn, delay) {
let timer = null; // замыкание помнит таймер
return function (...args) {
clearTimeout(timer); // отменяем прошлый
timer = setTimeout(() => fn(...args), delay);
};
}
let calls = 0;
const search = debounce(() => { calls++; }, 100);
search(); search(); search(); // быстрые подряд — должен сработать один раз
setTimeout(() => console.log("вызовов реально:", calls), 200);
Вывод:
вызовов реально: 1
Три быстрых вызова подряд схлопнулись в один: каждый новый сбрасывал таймер предыдущего, и сработал только последний, когда поток вызовов прекратился.
Реализация throttle
Идея: запоминаем время последнего вызова и пропускаем новые, пока не прошёл интервал. Здесь без таймеров — через сравнение времени.
function throttle(fn, interval) {
let last = 0; // время последнего вызова
return function (...args) {
const now = Date.now();
if (now - last >= interval) {
last = now;
fn(...args);
}
};
}
let count = 0;
const onScroll = throttle(() => { count++; }, 1000);
onScroll(); // первый проходит
onScroll(); // сразу следом — заблокирован
onScroll();
console.log("сработало раз:", count);
Вывод:
сработало раз: 1
Первый вызов прошёл, а следующие в пределах интервала отброшены — обработчик «троттлится» до одного раза в секунду.
Как отвечать на собеседовании
- debounce — «подожди, пока перестанут печатать, и сделай один запрос».
- throttle — «делай не чаще, чем раз в N миллисекунд».
- Оба основаны на замыкании, которое хранит состояние между вызовами.
Итог
- Оба приёма ограничивают частоту вызовов тяжёлых обработчиков.
debounceждёт паузу и делает один вызов;throttleограничивает частоту.- Реализуются через замыкание, хранящее таймер или время последнего вызова.