Реализуйте debounce(fn, delay) — обёртку, которая откладывает вызов fn до тех пор, пока между вызовами не пройдёт пауза в delay миллисекунд. Каждый новый вызов сбрасывает таймер.
Пример
const log = debounce((text) => console.log(text), 100);log('a');log('ab');log('abc'); // только этот выполнится через 100мс после последнего вызова// -> abc
Решение
Оптимальное решение (trailing)
function debounce(func, delay) { let timer; return function (...args) { clearTimeout(timer); // каждый вызов сбрасывает предыдущий таймер timer = setTimeout(() => { func.apply(this, args); // сохраняем контекст и аргументы }, delay); };}
Вариант с leading + trailing и методом cancel
function debounce(func, delay, { leading = false } = {}) { let timer; function debounced(...args) { const callNow = leading && !timer; clearTimeout(timer); timer = setTimeout(() => { timer = null; if (!leading) func.apply(this, args); // trailing }, delay); if (callNow) func.apply(this, args); // leading edge } debounced.cancel = () => { clearTimeout(timer); timer = null; }; return debounced;}
debounce vs throttle
debounce — ждёт паузу: выполнит, когда события перестанут приходить (поиск, resize, автосохранение).
throttle — выполняет не чаще раза в интервал, пока события идут (скролл, drag, rate limit).