Обработка событий

Зачастую при обработке таких событий как: scroll, click, keyup и т.д. возникает необходимость обрабатывать не каждое событие, а только последнее.

В каких случаях необходимо?

  • Подряд возникает несколько событий с одинаковым типом

  • Нет необходимости в получении результата обработки промежуточных событий

  • Обработка занимает длительное время

Пример №1

Пользователь изменяет количество товара в корзине интернет-магазина

Как мы видим, пересчет корзины происходит не при каждом изменении количества товара, а только после прекращения кликов.

 

Пересчет происходит на сервере, поэтому нет смысла тратить серверные ресурсы на промежуточные пересчеты, которые устареют за время выполнения XHR-запросов.

 

Если бы пересчет был моментальный, то пользователь наблюдал бы мельтешащие цифры.

Где еще может пригодиться такое поведение?

  • Отображение многоуровневых меню по наведению курсора мыши
  • Выпадающие подсказки для строки поиска
  • Применение фильтров в каталогах
  • и много других случаев

Как реализовать?

По-прежнему необходимо получать каждое событие, но обрабатывать только то, после которого в течение некоторого времени не произошло новых событий.


Для реализации пригодятся таймеры.


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

Обычная обработка события

document.addEventListener('click', () => {
    console.log('clicked')
})

Отложенная обработка через таймер

let timer = null
document.addEventListener('click', () => {
    if(timer) window.clearTimeout(timer)
    
    timer = window.setTimeout(() => {
        console.log('clicked')
    }, 1000)
})

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

Минусы приведенного примера

Универсальная функция

function debounce(func, time) {
  let iTimeout = null
  return (...args) => {
    if(iTimeout) {
      window.clearTimeout(iTimeout)
    }
    iTimeout = window.setTimeout(() => {
      func(...args)
      iTimeout = null
    }, time)
  }
}
const onClickDebounced = debounce(() => {
  console.log('clicked')
}, 1000)
document.addEventListener('click', onClickDebounced)

Хорошая реализация функции debounce включена в библиотеку Lodash

Работа с событиями

By evgenysm

Работа с событиями

  • 48