Асинхронный JavaScriptТаймерыhard

Throttle

Эта задача похожа на задачу debounce.

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

И точно так же функция throttle принимает функцию fn и время ms, а возвращает новую функцию, которая вызывает fn, но контролирует, чтобы вызовы происходили не слишком часто — не чаще чем раз в ms миллисекунд.

Главное отличие в том, что throttle старается вызывать функцию fn как можно чаще (но все еще не чаще, чем раз в ms миллисекунд).

Пример

На картинке ниже изображены вызовы функции с задержкой равной 400 мс.

Верхняя серия прямоугольников — вызовы функции throttledFn. Один прямоугольник означает 100 мс. Например, первый зеленый вызов произошел в момент времени 200 мс.

Нижняя серия прямоугольников показывает, когда реально произошли вызовы исходной функции fn. Например, зеленый вызов по факту произошел в 400 мс, так как нам нужно было подождать хотя бы 400 мс после первого синего вызова, который произошел в 0 мс.

Код для запуска

Комментариями помечены вызовы fn, которые фактически произошли. 0, 400 и 800, 1200, 1900, 2300 — время в мс, когда они произошли.

function fn(...args) { console.log({ args, time: Date.now() - start, }); } const throttledFn = throttle(fn, 400); let start = Date.now(); setTimeout(() => throttledFn(1, "blue"), 0); // 0 setTimeout(() => throttledFn(2, "pink"), 100); // setTimeout(() => throttledFn(3, "green"), 200); // 400 setTimeout(() => throttledFn(4, "pink"), 700); // 800 setTimeout(() => throttledFn(5, "pink"), 1000); // 1200 setTimeout(() => throttledFn(6, "green"), 1900); // 1900 setTimeout(() => throttledFn(7, "pink"), 2000); // setTimeout(() => throttledFn(8, "blue"), 2100); // setTimeout(() => throttledFn(9, "green"), 2200); // 2300