Разбор debounce() в lodash
Tags: javascript, react, node, tutorial
Published: 2023-01-28 13:18:33

Функция `debounce` - это обёртка над вашей функцией, которая позволяет отменить и отложить на какое-то время её повторные вызовы разными способами.


## Простой, но частоиспользующийся пример
Рассмотрим следующий код React приложения:

``` js
import { debounce } from "lodash";
import React, { useRef } from "react";

const HomePage = () => {
  const counter = useRef(1);

  const handleClick = debounce(
    (count) => {
      console.log("click happened!", count);
    },
  );

  return (
    <button
      onClick={() => {
        counter.current += 1;
        handleClick(counter.current); // Вызов функции №1
        handleClick(counter.current); // Вызов функции №2
        handleClick(counter.current); // Вызов функции №3
      }}
    >
      Нажми меня
    </button>
  );
};

export default HomePage;
```
Здесь используется "записывающая" способность рефов в React. Если вы не знакомы с ней, прошу сначала прочитать официальную документацию.

Обёртка, в которую мы обернули нашу функцию отклоняет 2-ой и 
3-ий вызов функции при клике на кнопку. А точнее она запоминает последний (3-ий) и затем выполняет его.

![Скриншот результата кода](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f2t7es9bpk6at4kcsh1y.png)


Зачастую в React приложении идёт многоповторный перерендеринг из-за частых изменений со стороны пользователя. Чтобы не нагружать систему, мы можем воспользоваться данной функцией. Чаще всего она может пригодиться в ситуации, когда пользователь вводит в input какое-либо содержимое и происходит ререндер при вводе каждого символа. Так как нам это не нужно, мы можем отложить его на n-ое количество времени.



## Параметры функции

`debounce(func, [time], [options])`

`func` - функция, которую необходимо обернуть
`time` - время в миллисекундах до следующего вызова
`options` - набор дополнительных параметров в виде объекта

`[options.leading]` (boolean, false по-умолчанию) - если `true`, то разрешает запуск функции моментально, не дожидаясь выставленного в параметре `time` времени. Последующие вызовы будут отклоняться до тех пор пока не пройдёт заданное время. По истечению будет запущен последний вызов функции.

`[options.maxWait]` (number) - максимальное время которое функция не будет вызываться при её многократном вызове. Дело в том, что если функция будет вызываться чаще, заданного времени в параметре `time`, то таймер будет каждый раз сбрасываться и наша функция не будет выполнена до тех пор, пока на протяжении n времени её не будут трогать. Если мы задаём этот параметр, то когда истечёт заданное в нём время, функция будет принудительно вызвана.

`[options.trailing]` (boolean, true по-умолчанию) - противоположность `leading`.
Если задан как `true`, то разрешает запуск функции по прошествии заданного в параметре `time` времени. Если `false`, то соответственно запрещает.

Если мы одновременно зададим  `{ leading: true, trailing: true }`, то у нас из одного вызова функции получится сразу два. Первый будет сразу, а второй по прошествии заданного времени.

Если всё ещё не понятно, то рекомендую запустить локально данный пример с разными настройками данной функции

``` js
 const handleClick = debounce(
    (count) => {
      console.log("click happened!", count);
    },
    3000,
    { leading: true, maxWait: 3500, trailing: true }
  );
```

## Методы функции

Помимо параметров, данная функция имеет 2 метода:

`cancel()` - отменяет отложенный вызов до его запуска
`flush()` - наоборот, запускает отложенный вызов раньше времени

Добавим 2 элемента к предыдущему коду:

``` js
<button
  onClick={() => {
    handleClick.cancel();
  }}
  >
  Cancel
</button>

<button
  onClick={() => {
    handleClick.flush();
   }}
  >
  Call immediately
</button>
```