Для чего нужна функция debounce и как она работает

02.09.2018 / oberset

Функция debounce возвращает обертку, которая откладывает вызов исходной функции на определенное время.

Вот как это обычно выглядит в коде: const myFoo = () => console.log('Called!'); const myFooDebounced = debounce(myFoo, 200); myFooDebounced(); myFooDebounced(); // выполнится 1 раз через 200 мс Мы передаем исходную функцию в качестве параметра в debounce и получаем новую функцию-обертку, которая уже будет выполняться с задержкой в 200 мсек. Если в течение этого промежутка времени произойдет несколько вызовов myFooDebounced (как в примере выше), то исходная функция все равно вызовется только 1 раз с задержкой в 200 мс с момента последнего вызова myFooDebounced.

Где требуется применение debounce?

Обычно debounce используют, если исходная функция вызывается чаще, чем это требуется. Например, DOM-события mousemove, resize, scroll генерируют очень частые вызовы обработчиков, поэтому в ряде случаев было бы полезно обернуть такие обработчики в debounce. Другое применение – контроль пользовательского ввода текста: если при изменении поля INPUT требуется передавать на сервер текущее введенное значение, это может создать большое количество однотипных запросов, особенно если пользователь печатает очень быстро. В этом случае тоже весьма кстати будет ограничить число вызовов обработчика с помощью debounce.

Как работает debounce

Теперь, когда мы знаем, где может потребоваться debounce, рассмотрим как эта функция работает изнутри. Вот пример простейшей реализации функции (подобные примеры иногда требуют написать на собеседовании): const debounce = (callback, delay) => { let timerId; return (...args) => { timerId && clearTimeout(timerId); timerId = setTimeout( () => callback(...args), delay ); } }; const foo = (val) => console.log(val); const debounced1 = debounce(foo, 1000); const debounced2 = debounce(foo, 2000); for (let i = 0; i < 10; i++) { debounced1('Called One!'); // Вызовется через 1 сек debounced2('Called Two!'); // Вызовется через 2 сек }

В примере выше, при каждом вызове debounce мы сбрасываем текущий "таймаут" и устанавливаем новый, гарантируя время задержки, переданное в качестве второго параметра. Мы вызываем наши функции-обертки в цикле, но фактически каждая из функций вызовется только 1 раз (через 1 и 2 секунды соответственно).

Готовые реализации debounce

Конечно же, нет смысла писать каждый раз подобную функцию самому (если вы не сидите с листком бумаги на собеседовании), поэтому можно воспользоваться готовым решением. Неплохая реализация debounce есть в библиотеке Lodash. // Lodash доступна через _ window.addEventListener('resize', _.debounce(e => { console.log(window.innerWidth, window.innerHeight); }, 100)); В JQuery и Angular также есть свои реализации этой функции.

Обзоры по теме:
Комментарии (0)

Зарегистрируйтесь или авторизуйтесь, чтобы оставлять комментарии.