52 lines
1.1 KiB
JavaScript
52 lines
1.1 KiB
JavaScript
|
//@ts-check
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* Creates a throttled function that only invokes the provided function at most
|
||
|
* once per within a given number of milliseconds.
|
||
|
*
|
||
|
* @template {(...args: any) => any } F
|
||
|
* @template {ReturnType<F>} R
|
||
|
* @template {Parameters<F>} P
|
||
|
* @param {F} func
|
||
|
* @param {number} [firingRateMs] Firing rate (50ms by default)
|
||
|
*/
|
||
|
export const throttle = (func, firingRateMs = 50) => {
|
||
|
/** @type {R} */
|
||
|
let lastResult;
|
||
|
|
||
|
/** @type {number} */
|
||
|
let last = 0;
|
||
|
|
||
|
/** @type {null|P} */
|
||
|
let funcArguments;
|
||
|
|
||
|
/** @type {number} */
|
||
|
let timeoutID = 0;
|
||
|
|
||
|
const call = () => {
|
||
|
timeoutID = 0;
|
||
|
last = +new Date();
|
||
|
lastResult = func.apply(null, funcArguments);
|
||
|
funcArguments = null;
|
||
|
};
|
||
|
|
||
|
/***
|
||
|
* @param {P} args
|
||
|
*/
|
||
|
const throttled = (...args) => {
|
||
|
funcArguments = args;
|
||
|
const delta = new Date().getTime() - last;
|
||
|
if (!timeoutID)
|
||
|
if (delta >= firingRateMs) {
|
||
|
call();
|
||
|
} else {
|
||
|
timeoutID = setTimeout(call, firingRateMs - delta);
|
||
|
}
|
||
|
return lastResult;
|
||
|
};
|
||
|
|
||
|
return throttled;
|
||
|
};
|
||
|
|
||
|
export default throttle
|