В чем разница debounce и throttle и когда использовать каждый
Что проверяют
Понимаете ли вы разницу на уровне поведения, а не определения, и подберёте ли правильный приём под сценарий.
Как отвечать
debounce откладывает вызов до паузы: таймер сбрасывается на каждом новом событии, и функция выполняется один раз, когда события прекратились на заданное время. throttle пропускает вызов не чаще раза в интервал, независимо от того, сколько событий пришло.
Проще всего объяснить на потоке событий: если пользователь печатает без остановки, debounce не выполнит ничего до паузы, а throttle будет срабатывать равномерно, скажем раз в 200 миллисекунд.
Когда что:
- debounce: поиск по мере ввода, автосохранение черновика, валидация поля, запрос подсказок. Важен итог, а не промежуточные состояния;
- throttle: обработка прокрутки, движение мыши, изменение размера окна, отправка событий аналитики. Важна регулярность и ограничение нагрузки.
const debounce = (fn, ms) => {
let t;
return (...args) => { clearTimeout(t); t = setTimeout(() => fn(...args), ms); };
};Полезные уточнения к ответу: у обеих функций бывает вызов по переднему или заднему фронту, и от этого зависит, сработает ли она сразу; при отмене нужно чистить таймер (в React в функции очистки эффекта); для прокрутки и видимости часто правильнее не throttle, а IntersectionObserver или requestAnimationFrame, потому что они привязаны к отрисовке.
Где спотыкаются
Создают функцию заново на каждом рендере компонента, из-за чего таймер сбрасывается и приём не работает.
Ставят debounce на прокрутку и получают срабатывание только после остановки, хотя нужна регулярная реакция.
Забывают отменить отложенный вызов при размонтировании и обновляют состояние уже удалённого компонента.