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

Для чего нужна функция 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 также есть свои реализации этой функции.

Примеры использования Array reduce в Javascript

Метод reduce(callback, initialValue) возвращает результат функции callback, которая применяется к каждому элементу массива.

Как получить локальный IP-адрес пользователя на Javascript

Пример получения локального IP-адреса клиентской машины на Javascript с помощью HTML5 RTCPeerConnection API.

ScanFS — альтернативный инструмент поиска файлов и папок для Windows

ScanFs — продвинутая утилита, предназначенная для быстрого поиска файлов и папок на диске с применением различных фильтров.