UNPKG

vanilla-performance-patterns

Version:

Production-ready performance patterns for vanilla JavaScript. Zero dependencies, maximum performance.

136 lines (134 loc) 4.01 kB
/** * @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 };