vanilla-performance-patterns
Version:
Production-ready performance patterns for vanilla JavaScript. Zero dependencies, maximum performance.
136 lines (134 loc) • 4.01 kB
TypeScript
/**
* @fileoverview Advanced debounce and throttle implementations
* @author - Mario Brosco <mario.brosco@42rows.com>
@company 42ROWS Srl - P.IVA: 18017981004
* @module vanilla-performance-patterns/timing
*
* Pattern inspired by Lodash with additional features
* MaxWait option ensures execution even with continuous input
* Leading/trailing edge control for precise timing
*/
interface DebounceOptions {
/** Execute on leading edge (default: false) */
leading?: boolean;
/** Execute on trailing edge (default: true) */
trailing?: boolean;
/** Maximum time to wait before forced execution */
maxWait?: number;
}
interface ThrottleOptions {
/** Execute on leading edge (default: true) */
leading?: boolean;
/** Execute on trailing edge (default: true) */
trailing?: boolean;
}
interface DebouncedFunction<T extends (...args: any[]) => any> {
(...args: Parameters<T>): void;
/** Cancel pending execution */
cancel(): void;
/** Flush pending execution immediately */
flush(): ReturnType<T> | undefined;
/** Check if there's a pending execution */
pending(): boolean;
}
/**
* Advanced debounce with maxWait option
*
* @example
* ```typescript
* const search = debounce(
* async (query: string) => {
* const results = await api.search(query);
* updateUI(results);
* },
* 300,
* {
* maxWait: 1000, // Force execution after 1s even with continuous input
* leading: false,
* trailing: true
* }
* );
*
* // Type continuously - will execute after 300ms pause OR 1000ms max
* input.addEventListener('input', (e) => search(e.target.value));
* ```
*/
declare function debounce<T extends (...args: any[]) => any>(func: T, wait: number, options?: DebounceOptions): DebouncedFunction<T>;
/**
* Advanced throttle implementation
*
* @example
* ```typescript
* const handleScroll = throttle(
* () => {
* const scrollY = window.scrollY;
* updateParallax(scrollY);
* },
* 16, // 60fps
* { leading: true, trailing: false }
* );
*
* window.addEventListener('scroll', handleScroll, { passive: true });
* ```
*/
declare function throttle<T extends (...args: any[]) => any>(func: T, wait: number, options?: ThrottleOptions): DebouncedFunction<T>;
/**
* Request animation frame throttle for smooth animations
*
* @example
* ```typescript
* const animate = rafThrottle(() => {
* element.style.transform = `translateX(${x}px)`;
* });
*
* slider.addEventListener('input', animate);
* ```
*/
declare function rafThrottle<T extends (...args: any[]) => any>(func: T): DebouncedFunction<T>;
/**
* Idle callback throttle for non-critical updates
*
* @example
* ```typescript
* const saveAnalytics = idleThrottle(() => {
* sendAnalytics(collectedData);
* });
*
* // Will execute during browser idle time
* document.addEventListener('click', saveAnalytics);
* ```
*/
declare function idleThrottle<T extends (...args: any[]) => any>(func: T, options?: IdleRequestOptions): DebouncedFunction<T>;
/**
* Memoize function results with optional TTL
*
* @example
* ```typescript
* const expensiveCalc = memoize(
* (n: number) => {
* console.log('Computing...');
* return fibonacci(n);
* },
* {
* maxSize: 100,
* ttl: 60000, // Cache for 1 minute
* keyResolver: (n) => String(n)
* }
* );
* ```
*/
interface MemoizeOptions<T extends (...args: any[]) => any> {
/** Custom key resolver */
keyResolver?: (...args: Parameters<T>) => string;
/** Maximum cache size */
maxSize?: number;
/** Time to live in ms */
ttl?: number;
/** Use WeakMap for object keys */
weak?: boolean;
}
declare function memoize<T extends (...args: any[]) => any>(func: T, options?: MemoizeOptions<T>): T & {
cache: Map<string, any> | WeakMap<object, any>;
};
export { debounce, idleThrottle, memoize, rafThrottle, throttle };
export type { DebounceOptions, DebouncedFunction, MemoizeOptions, ThrottleOptions };