@stnekroman/tstools
Version:
Set of handy tools for TypeScript development
82 lines (68 loc) • 2.88 kB
text/typescript
import {Functions} from "../Functions";
/**
* Ported patterns from http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
*/
export namespace Throttle {
export interface ThrottleFunction<ARGS extends unknown[] = void[]> extends Functions.ArgsFunction<ARGS, void> {
cancel(): void; // cancels and discards any pending calls, but continues to serve new incoming calls
}
/**
* Returns function, which will remember call arguments from it's last invocation,
* and will fire given callback after specified timeout with previously collected arguments.
* @param callback to be called, throttled by timeout
* @param timeout in milliseconds
*/
export function throttle<ARGS extends unknown[] = void[]>(callback: Functions.ArgsFunction<ARGS, void>,
timeout: number
): ThrottleFunction<ARGS> {
let lastArgs : ARGS | undefined;
let timerId : NodeJS.Timeout | number | undefined;
const throttleFunction: ThrottleFunction<ARGS> = (...args: ARGS): void => {
lastArgs = args;
if (timerId === undefined) {
timerId = setTimeout((): void => {
callback(...lastArgs!);
lastArgs = undefined;
timerId = undefined;
}, timeout);
}
};
throttleFunction.cancel = (): void => {
if (timerId !== undefined) {
clearTimeout(timerId);
timerId = undefined;
}
lastArgs = undefined;
};
return throttleFunction;
}
/**
* Returns functions, which will remember arguments from it's last call and (re)schedule given callback to fire (with last arguments)
* after last function call with specified timeout. New function call delays actual callback further.
* @param callback to call after timeout
* @param timeout in milliseconds
*/
export function deferring<ARGS extends unknown[] = void[]>(callback: Functions.ArgsFunction<ARGS, void>, timeout: number): ThrottleFunction<ARGS> {
let lastArgs: ARGS | undefined;
let timerId: NodeJS.Timeout | number | undefined;
const throttleFunction: ThrottleFunction<ARGS> = (...args: ARGS): void => {
lastArgs = args;
if (timerId !== undefined) {
clearTimeout(timerId);
}
timerId = setTimeout((): void => {
callback(...lastArgs!);
lastArgs = undefined;
timerId = undefined;
}, timeout);
};
throttleFunction.cancel = (): void => {
if (timerId !== undefined) {
clearTimeout(timerId);
timerId = undefined;
}
lastArgs = undefined;
};
return throttleFunction;
}
}