Debounce и throttle для событий

В веб-разработке часто возникает необходимость контролировать частоту выполнения функций, вызываемых событиями, такими как scroll, resize или input. Неконтролируемое выполнение функций при частых событиях может привести к падению производительности, поэтому применяются техники debounce и throttle. Эти методы особенно актуальны при работе с библиотекой Isotope, где динамическое фильтрование, сортировка и анимация элементов могут создавать нагрузку на браузер.


Debounce

Debounce — это техника, при которой функция вызывается только после того, как событие прекратилось на определённый промежуток времени. Другими словами, функция выполняется один раз после серии быстрых повторяющихся событий.

Основные моменты:

  • Позволяет избежать лишних вызовов при непрерывном событии.
  • Идеально подходит для ввода текста (input), изменения размера окна (resize) и фильтрации элементов.
  • Реализуется с использованием setTimeout и clearTimeout.

Пример использования с Isotope:

// Инициализация Isotope
var iso = new Isotope('.grid', {
  itemSelector: '.grid-item',
  layoutMode: 'masonry'
});

// Debounce функция
function debounce(fn, delay) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn.apply(this, args), delay);
  };
}

// Фильтрация с debounce
const filterItems = debounce(function(filterValue) {
  iso.arrange({ filter: filterValue });
}, 300);

// Пример привязки к кнопкам фильтров
document.querySelectorAll('.filter-button-group button').forEach(button => {
  button.addEventListener('click', () => {
    const filterValue = button.getAttribute('data-filter');
    filterItems(filterValue);
  });
});

В этом примере при частых нажатиях на кнопки фильтров Isotope перестанет перерендеривать элементы мгновенно, а будет выполнять фильтрацию только после 300 мс паузы между событиями.


Throttle

Throttle — это техника, при которой функция вызывается не чаще, чем раз в заданный промежуток времени, независимо от того, сколько раз событие произошло. В отличие от debounce, throttle гарантирует периодическое выполнение функции при непрерывных событиях.

Основные моменты:

  • Используется для событий с высокой частотой, таких как scroll, mousemove.
  • Позволяет поддерживать плавность интерфейса, снижая нагрузку на браузер.
  • Реализуется через проверку времени последнего вызова функции.

Пример использования с Isotope:

// Throttle функция
function throttle(fn, limit) {
  let lastCall = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastCall >= limit) {
      lastCall = now;
      fn.apply(this, args);
    }
  };
}

// Перестройка Isotope при скролле с throttle
const handleScroll = throttle(function() {
  iso.layout();
}, 200);

window.addEventListener('scroll', handleScroll);

В этом примере метод layout Isotope будет выполняться не чаще одного раза в 200 мс при прокрутке страницы, что предотвращает падение производительности при активном скролле.


Отличия Debounce и Throttle

Характеристика Debounce Throttle
Когда вызывается После завершения серии событий С периодичностью во время события
Применение Ввод текста, фильтры, resize Scroll, drag, mousemove
Основной эффект Функция выполняется реже, только один раз Функция выполняется с постоянным интервалом

Практическое применение в Isotope

Debounce отлично подходит для динамической фильтрации элементов:

  • Пользователь выбирает фильтр, и Isotope не начинает немедленное перераспределение каждого элемента подряд, а делает это один раз после завершения ввода.

Throttle оптимален для перерасчёта расположения элементов при прокрутке или изменении размера окна:

  • При скролле страницы или изменении размера окна вызывается layout, но с ограниченной частотой, что предотвращает мерцание и лаги анимации.

Комбинирование подходов:

Можно комбинировать debounce и throttle для максимальной оптимизации:

  • Throttle для событий с высокой частотой (scroll, resize).
  • Debounce для событий с низкой частотой и конечным действием (клики, input).

Советы по оптимизации Isotope с использованием Debounce и Throttle

  1. Минимизировать лишние вычисления: никогда не вызывать arrange или layout напрямую на каждое событие.
  2. Подбирать интервалы корректно: для scroll достаточно 100–250 мс, для фильтров 200–500 мс.
  3. Сохранять контекст: всегда использовать apply или call внутри обёртки, чтобы сохранить контекст и переданные аргументы.
  4. Тестировать производительность: проверять FPS и время рендеринга, особенно на мобильных устройствах.

Эти техники значительно повышают отзывчивость интерфейса и позволяют библиотеке Isotope работать плавно даже с большим количеством элементов.