UNPKG

debounce-throttle-utils

Version:

A lightweight utility library that provides debounce and throttle functions to optimize performance by controlling the execution frequency of functions.

107 lines (89 loc) 3.42 kB
type Fn = (...args: any[]) => void; interface DebounceOptions { leading?: boolean; // Execute on the leading edge trailing?: boolean; // Execute on the trailing edge } interface ThrottleOptions { leading?: boolean; // Execute on the leading edge trailing?: boolean; // Execute on the trailing edge } /** * Debounce function - Delays the execution of the passed function until the user stops calling it for a specified delay. * * @param func The function to debounce * @param delay The time to wait before executing the function, in milliseconds * @param options The options for leading/trailing execution * @returns A debounced function */ function debounce(func: Fn, delay: number, options: DebounceOptions = {}): Fn & { cancel: () => void } { let timer: NodeJS.Timeout; let lastCallTime = 0; // Use a normal function here to access `this` context const debouncedFn = function (this: any, ...args: any[]) { const context = this; // Explicitly refer to the correct `this` value const now = Date.now(); const isLeading = options.leading && !lastCallTime; clearTimeout(timer); if (isLeading) { func.apply(context, args); // Apply with the correct context and arguments } timer = setTimeout(() => { if (options.trailing) { func.apply(context, args); // Apply with the correct context and arguments } lastCallTime = now; }, delay); }; // Cancel the pending debounced function execution debouncedFn.cancel = function () { clearTimeout(timer); }; return debouncedFn; } /** * Throttle function - Ensures the passed function is executed at most once in a given period of time. * * @param func The function to throttle * @param limit The time interval in milliseconds to limit the execution of the function * @param options The options for leading/trailing execution * @returns A throttled function with flush method */ function throttle(func: Fn, limit: number, options: ThrottleOptions = {}): Fn { let lastFunc: NodeJS.Timeout; let lastTime: number = 0; let lastArgs: any[] = []; // Store the arguments to use in flush // Use a normal function here to access `this` context const throttledFn = function (this: any, ...args: any[]) { const context = this; // Explicitly refer to the correct `this` value const now = Date.now(); const isLeading = options.leading && !lastTime; if (isLeading) { func.apply(context, args); // Apply with the correct context and arguments lastTime = now; } const remainingTime = limit - (now - lastTime); if (remainingTime <= 0) { clearTimeout(lastFunc); func.apply(context, args); // Apply with the correct context and arguments lastTime = now; } else if (options.trailing) { clearTimeout(lastFunc); lastFunc = setTimeout(() => { func.apply(context, args); // Apply with the correct context and arguments lastTime = Date.now(); }, remainingTime); } // Store the latest arguments for flushing lastArgs = args; }; // Flush the pending throttled function execution throttledFn.flush = function () { if (lastFunc) { clearTimeout(lastFunc); func.apply(this, lastArgs); // Apply with the correct context and the stored arguments } }; return throttledFn; } // Exporting the debounce and throttle functions export { debounce, throttle };