Throttling и Debouncing в JavaScript

Категория: JavaScript

Дектораторы ф-ций Throttle и Debouncing применяются для уменьшения частоты вызова callback'ов.

Примечание

Рассмотрите возможность использования функционала debounce из библиотеки lodash - https://lodash.com/docs#debounce.

Debouncing (устранение дребезга) "после"

Если нужно: Запускать 1 раз после N сек простоя.

Частые запуски/вызовы игнорируются, пока они не прекратятся на заданный период времени. После простоя N сек - вызывается функция/обработчик.

Ф-ция debounce сбрасывает счетчик при каждой попытке вызова callback раньше указанной задержки (delay).

Применяется для тяжелых обработчиков на событиях input, keyup/keydown, resize, click.

$('input').on('input', $.debounce(function(e){
  // обрабатываем ввод текста только после того, 
  // как пользователь перестанет вводить текст на 300ms
}, 300));

Пример реализации debounce() ф-ции:

const debounce = function(fn, time) {
    let timeout;

    return function() {
        let self = this;
        const functionCall = function() {
            return fn.apply(self, arguments);
        };
        clearTimeout(timeout);
        timeout = setTimeout(functionCall, time);
    }
};

Пример реализации debounce() ф-ции с привязкой контекста this:

const debounce = function(fn, time, bind) {
    let timeout;

    return function() {
        const functionCall = function() {
            return fn.apply(bind, arguments);
        };
        clearTimeout(timeout);
        timeout = setTimeout(functionCall, time);
    }
};

Throttling (дроссель) "шаг, торможение"

Если нужно: Запускать не чаще, чем 1 раз каждые N сек.

Придерживает частые вызовы до заданного периода/шага (предотвращает запуск функции, если она уже запускалась недавно).

Применяется: для тяжелых обработчиков событий mousemove, scroll.

$(window).mousemove($.throttle(function(e){
  // обрабатываем событие mousemove каждые 200ms
}, 200));

Реализации обеих ф-ций можно взять у Filatov Dmitry на Github - https://github.com/dfilatov/jquery-plugins/blob/master/src/jquery.debounce/jquery.debounce.js.

bower install https://raw.githubusercontent.com/dfilatov/jquery-plugins/master/src/jquery.debounce/jquery.debounce.js

Эти же декораторы, несколько переписанные, есть в репозитории - https://github.com/lolmaus/jquery.timer-tools (ИМХО, добавление суффиксов $.debounceFirst и $.debounceLast, несколько излишне).

js-throttle-debounce

Еще одна реализация throttle, debounce на основе расширения прототипа функций. Github: https://github.com/emn178/js-throttle-debounce

Установка:

bower install js-throttle-debounce

Пример:

var handlerDebounce = function(e) {
  console.log('выполняется после 2 сек после того, как мы прекратим дергать метод');
}.debounce(2000);

$('#editor').on('DOMSubtreeModified', handlerDebounce);

#debounce, #debouncing, #throttle, #throttling, #jquery plugins