Что такое дебаунс?

Debounce — это функция-оболочка, которая ограничивает количество выполнений переданной ей функции определенным периодом времени.

Удобное использование

Допустим, при вводе текста в инпут мы хотим отправить запрос на сервер выпадающего списка вариантов для введенного значения.

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

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

Как настроить дебаунс?

Чтобы правильно реализовать debounce, нам нужно, чтобы каждый следующий вызов целевой функции «знал» о своем предыдущем вызове, и на основе этих данных debounce решает, выполнять ли функцию или отложить ее.

Для debounce “эти данные” являются идентификатором тайм-аута.

Что с замыканиями?

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

Что такое закрытие?

Замыкание — это функция, которая инкапсулирует и возвращает функцию вместе с ее окружением.

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

Переменные, объявленные в этом окружении (в частности, в замыкании), с одной стороны, будут недоступны извне этого окружения. Особенностью языка javascript является то, что только он и его дочерние среды имеют доступ к переменным среды, при условии, что доступ запрашивается после объявления.

Второе свойство заключается в том, что окружение функции не удаляется из памяти сразу после выполнения самой функции. Таким образом, переменные, объявленные в замыкании, могут быть «разделены» между различными вызовами функции, возвращаемой замыканием.

ЧИТАТЬ   При нападении на школу в Пакистане погибли шесть учителей

Теперь посмотрим, как это будет работать на практике.

Во-первых, давайте объявим функцию закрытия debounce, которая принимает функцию обратного вызова и ее предел времени выполнения. Он будет содержать переменную, в которой хранится идентификатор тайм-аута каждого последующего вызова:

export const debounce = (callback, interval) => {
  let prevTimeoutId;

  return (...args) => {
    prevTimeoutId = setTimeout(() => {
      callback(args);
    }, limit);
  }
}

Мы передаем аргументы возвращаемой функции обратному вызову. Обратите внимание на порядок, в котором аргументы передаются при закрытии: …args — это аргументы, которые функция получит при последнем (то есть втором) вызове — например, действие объекта события, если, скажем, дебаунсер передается как обработчик события.

Также логика такова: при следующем вызове функции нам нужно очистить предыдущий вызов из памяти — это можно сделать по id таймаута с помощью функции clearTimeout. Далее нам нужно объявить новый таймаут, сохранить его ID и вернуть новую функцию:

const debounce = (callback, interval = 0) => {
  let prevTimeoutId;
 
  return (...args) => {
    clearTimeout(timeoutId);
    prevTimeoutId = setTimeout(() => callback(...args), interval);
  }
}

Теперь, если мы теперь хотим использовать наше подавление дребезга на входе, это будет выглядеть так:

document.querySelector('input').addEventListener(
  'input',
  debounce(ev => console.log(ev.target.value), 1000)
);

А при наборе символов во вводе на консоль будут выведены только значения, введенные с интервалом в одну секунду.

Добавим отзывчивости!

Если мы хотим использовать debounce в реагирующем компоненте, его необходимо преобразовать в пользовательский реагирующий хук, чтобы предыдущий идентификатор тайм-аута и возвращаемая функция не исчезли из памяти. Это делается с помощью хуков useRef и useCallback соответственно:

const useDebounce = (callback, interval = 0) => {
  const prevTimeoutIdRef = React.useRef();

  return React.useCallback(
    (...args) => {
      clearTimeout(prevTimeoutIdRef.current);
      prevTimeoutIdRef.current = setTimeout(() => {
        clearTimeout(prevTimeoutIdRef.current);
        callback(...args);
      }, interval);
    },
    [callback, interval]
  );
};

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

ЧИТАТЬ   Санкции США убивают старейший в России магазин электроники спустя 30 лет

Вот и все.

Надеюсь, вам понравилось это увлекательное путешествие в мир анти-отскоков и замыканий.

Я рекомендую следующую статью о замыканиях:

https://learn.javascript.ru/close

СПАСИБО

Source

От admin