tickle/modules/utils/throttle.mjs

52 lines
1.1 KiB
JavaScript
Raw Normal View History

2023-06-07 20:07:47 +00:00
//@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