Chupurnov Valeriy
Chupurnov Valeriy
Front End Engineer

Тротлер на JS

Есть такой класс задач, которые надо выполнять не чаще чем раз в n период. К примеру отправлять данные на сервер, чтобы его не заспамить. В JS, да как и везде, такие функции называют затротленными. Приторможенными. А сам тротлер, это функция, которая возвращает другую функцию. Сколько бы не вызывай которую, она не выполнится чаще чем задано в тротлере.

Для одного проекта мне потребовалась такая функция, и на собеседованиях мы часто задаем такую задачку. Но в этот раз проект был такой, что хотелось только копипастить со stackoverflow. Бывает такое. Но первая ссылка была не на него а сюда: https://learn.javascript.ru/task/throttle

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

Вот ее код:

function throttle(func, ms) {

  let isThrottled = false,
    savedArgs,
    savedThis;

  function wrapper() {

    if (isThrottled) { // (2)
      savedArgs = arguments;
      savedThis = this;
      return;
    }

    func.apply(this, arguments); // (1)

    isThrottled = true;

    setTimeout(function() {
      isThrottled = false; // (3)
      if (savedArgs) {
        wrapper.apply(savedThis, savedArgs);
        savedArgs = savedThis = null;
      }
    }, ms);
  }

  return wrapper;
}

Поэтому я поискал еще, и нашел вот это чудо:

const throttle = (func, limit) => {
  let inThrottle
  return function() {
    const args = arguments
    const context = this
    if (!inThrottle) {
      func.apply(context, args)
      inThrottle = true
      setTimeout(() => inThrottle = false, limit)
    }
  }
}

Используем соотвественно примерно так:

document.body.addEventListener('mousemove', throttler((e) => {
   // Этот код будет выполняться не чаще чем раз в 100 миллисекунд
}, 100));

А к примеру в реакте тротлер можно использовать так:

function Area() {
    const onInput = throttle((e) => {
        sendToServer(e.target.value);
    },  1000);
    
    return <textarea onInput={onInput}/>
}

Используйте на здоровье.