Limit how often a function runs. Useful for scroll, resize, or input handlers.
export function throttle<T extends (...args: unknown[]) => unknown>(
fn: T,
delay: number
): (...args: Parameters<T>) => void {
let last = 0;
let timer: ReturnType<typeof setTimeout> | null = null;
return function throttled(this: unknown, ...args: Parameters<T>) {
const now = Date.now();
const remaining = delay - (now - last);
if (remaining <= 0) {
if (timer) clearTimeout(timer);
timer = null;
last = now;
fn.apply(this, args);
} else if (!timer) {
const self = this;
timer = setTimeout(() => {
last = Date.now();
timer = null;
fn.apply(self, args);
}, remaining);
}
};
}Throttle ensures the wrapped function runs at most once per delay ms. First call runs immediately; later calls are delayed until the interval has passed.
Use for scroll or resize handlers to avoid excessive work.
const onScroll = throttle(() => { /* update UI */ }, 100); window.addEventListener('scroll', onScroll);