Throttling и debouncing

В JavaScript при работе с событиями часто возникает необходимость контролировать частоту вызовов функций. События, такие как scroll, resize или input, могут срабатывать десятки и сотни раз в секунду, создавая нагрузку на браузер и замедляя работу приложения. Для решения этой задачи используют throttling и debouncing — два метода управления частотой вызовов функций.


Throttling

Throttling (ограничение частоты вызовов) гарантирует, что функция будет вызываться не чаще, чем заданный интервал времени. Это полезно, когда необходимо периодически обновлять состояние при непрерывном событии, но не каждое его срабатывание.

Пример реализации throttling:

function throttle(func, limit) {
    let lastFunc;
    let lastRan;
    return function(...args) {
        const context = this;
        if (!lastRan) {
            func.apply(context, args);
            lastRan = Date.now();
        } else {
            clearTimeout(lastFunc);
            lastFunc = setTimeout(function() {
                if ((Date.now() - lastRan) >= limit) {
                    func.apply(context, args);
                    lastRan = Date.now();
                }
            }, limit - (Date.now() - lastRan));
        }
    }
}

Применение:

window.addEventListener('scroll', throttle(() => {
    console.log('Прокрутка обработана!');
}, 200));

В данном примере функция срабатывает не чаще одного раза каждые 200 миллисекунд, даже если событие scroll происходит чаще.

Особенности:

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

Debouncing

Debouncing (устранение дребезга) обеспечивает вызов функции только после того, как событие перестало срабатывать в течение определенного времени. Это подходит для сценариев, когда результат важен только после завершения активности пользователя, например при вводе текста или изменении размеров окна.

Пример реализации debouncing:

function debounce(func, delay) {
    let timeoutId;
    return function(...args) {
        const context = this;
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
            func.apply(context, args);
        }, delay);
    }
}

Применение:

const input = document.querySelector('#search');
input.addEventListener('input', debounce(() => {
    console.log('Запрос отправлен!');
}, 300));

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

Особенности:

  • Идеально для поиска, автосохранения и валидации полей формы.
  • Уменьшает количество ненужных вызовов функций.
  • Обеспечивает выполнение кода только при окончании активности.

Отличия и выбор между throttling и debouncing

Параметр Throttling Debouncing
Частота вызова функции Ограничена фиксированным интервалом Вызов происходит только после паузы
Подходит для Событий с непрерывной активностью (scroll) Событий, где нужен результат после завершения действия (input)
Контроль нагрузки Равномерное распределение вызовов Отложенный вызов, минимизирует количество вызовов

Throttling и debouncing в сочетании с iziToast

iziToast — библиотека для уведомлений в браузере, которая позволяет показывать всплывающие сообщения пользователю. В сценариях с частыми событиями использование throttling или debouncing позволяет контролировать количество уведомлений, предотвращая их «навал» на экран.

Пример throttling с iziToast при скролле:

window.addEventListener('scroll', throttle(() => {
    iziToast.info({
        title: 'Информация',
        message: 'Вы прокрутили страницу!',
        position: 'topRight'
    });
}, 1000));

Пример debouncing с iziToast при вводе в поле поиска:

const searchInput = document.querySelector('#search');
searchInput.addEventListener('input', debounce(() => {
    iziToast.success({
        title: 'Поиск',
        message: 'Результаты обновлены',
        position: 'topRight'
    });
}, 500));

Использование этих подходов позволяет снизить нагрузку на интерфейс, избегать дублирующихся уведомлений и улучшить пользовательский опыт.


Рекомендации по практике

  1. Для событий с высокой частотой — использовать throttling.
  2. Для событий с логикой «после окончания действия» — использовать debouncing.
  3. Можно комбинировать оба метода при сложных сценариях, например throttling для промежуточных уведомлений и debouncing для итогового действия.
  4. Для iziToast важно контролировать количество одновременно отображаемых уведомлений, чтобы интерфейс оставался удобным.

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