Skip to content

throttle

Edit

Runs immediately, then drops calls until a specified interval has elapsed.

throttle.ts
export type ThrottledFunction<
Arguments extends unknown[],
Return,
This = unknown,
> = ((
this: This,
...args: Arguments
) => Return | undefined) & {
reset: () => void;
};
/** Runs immediately, then drops calls until the interval has elapsed. */
export const throttle = <This, Arguments extends unknown[], Return>(
fn: (this: This, ...args: Arguments) => Return,
intervalMs: number
): ThrottledFunction<Arguments, Return, This> => {
if (!Number.isFinite(intervalMs) || intervalMs < 0) {
throw new RangeError("intervalMs must be a finite, non-negative number");
}
let lastInvocation: number | undefined;
const throttled = function (
this: This,
...args: Arguments
): Return | undefined {
const now = Date.now();
if (
lastInvocation !== undefined &&
now >= lastInvocation &&
now - lastInvocation < intervalMs
) {
return undefined;
}
lastInvocation = now;
return Reflect.apply(fn, this, args) as Return;
};
return Object.assign(throttled, {
reset: () => {
lastInvocation = undefined;
},
});
};
Terminal
wget -O src/lib/throttle.ts https://raw.githubusercontent.com/jrTilak/lazykit/HEAD/registry/functions/throttle.ts
throttle.example.ts
import { throttle } from "./throttle";
const save = throttle((value: string) => {
console.log("Saving", value);
}, 1_000);
save("first"); // Runs immediately.
save("second"); // Dropped during the interval.
  • fn ((...args: A) => R) — Function invoked with the leading call’s arguments and receiver.
  • intervalMs (number) — Finite, non-negative interval in milliseconds.

A function returning R when invoked or undefined when dropped, plus reset() to reopen the interval immediately.