DEV Community

Viktor Savchenko
Viktor Savchenko

Posted on

Разбор debounce() в lodash

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

Простой, но частоиспользующийся пример

Рассмотрим следующий код React приложения:

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;
Enter fullscreen mode Exit fullscreen mode

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

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

Скриншот результата кода

Зачастую в 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 }, то у нас из одного вызова функции получится сразу два. Первый будет сразу, а второй по прошествии заданного времени.

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

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

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

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

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

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

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

<button
  onClick={() => {
    handleClick.flush();
   }}
  >
  Call immediately
</button>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)