UNPKG

vite-uni-dev-tool

Version:

vite-uni-dev-tool, debug, uni-app, 一处编写,到处调试

193 lines (164 loc) 5.07 kB
type ThrottleOptions = { leading?: boolean; trailing?: boolean; }; /** * 创建一个节流函数,在指定时间间隔内只执行一次原函数 * @param func 需要节流的函数 * @param wait 等待时间(毫秒) * @param options 配置选项 * @param options.leading 是否在开始时立即执行 * @param options.trailing 是否在延迟结束后执行最后一次调用 * @returns 节流后的函数 */ export function throttle<T extends (...args: any[]) => any>( func: T, wait: number, options: ThrottleOptions = {}, ): (...args: Parameters<T>) => ReturnType<T> | undefined { let timeout: NodeJS.Timeout | null = null; let lastArgs: Parameters<T> | null = null; let lastThis: any = null; let result: ReturnType<T> | undefined; let lastCallTime: number | null = null; const { leading = true, trailing = true } = options; const invokeFunc = (time: number) => { const args = lastArgs; const thisArg = lastThis; lastArgs = lastThis = null; lastCallTime = time; result = func.apply(thisArg, args!); return result; }; const leadingEdge = (time: number) => { lastCallTime = time; timeout = null; return leading ? invokeFunc(time) : undefined; }; const trailingEdge = (time: number) => { timeout = null; if (lastArgs && trailing) { return invokeFunc(time); } lastArgs = lastThis = null; return result; }; const remainingWait = (time: number) => { if (lastCallTime === null) return wait; const timeSinceLastCall = time - lastCallTime; return wait - timeSinceLastCall; }; const shouldInvoke = (time: number) => { if (lastCallTime === null) return true; const timeSinceLastCall = time - lastCallTime; return timeSinceLastCall >= wait || timeSinceLastCall < 0; }; const timerExpired = () => { const time = Date.now(); if (shouldInvoke(time)) { return trailingEdge(time); } timeout = setTimeout(timerExpired, remainingWait(time)); return undefined; }; const throttled = function (this: any, ...args: Parameters<T>) { const time = Date.now(); const isInvoking = shouldInvoke(time); lastArgs = args; lastThis = this; if (isInvoking) { if (timeout === null) { return leadingEdge(time); } } if (timeout === null) { timeout = setTimeout(timerExpired, wait); } return result; }; throttled.cancel = () => { if (timeout !== null) { clearTimeout(timeout); } lastCallTime = null; timeout = lastArgs = lastThis = null; }; return throttled; } type DebouncedFunction<T extends (...args: any[]) => any> = (( ...args: Parameters<T> ) => ReturnType<T> | undefined) & { cancel: () => void; flush: () => ReturnType<T> | undefined; }; /** * 创建一个防抖函数,该函数在最后一次调用后等待指定时间才执行。 * @param func 需要防抖的函数 * @param wait 等待时间(毫秒) * @param immediate 是否在第一次调用时立即执行 * @returns 防抖后的函数 */ export function debounce<T extends (...args: any[]) => any>( func: T, wait: number, immediate: boolean = false, ): DebouncedFunction<T> { let timeout: ReturnType<typeof setTimeout> | null = null; let lastArgs: Parameters<T> | null = null; let lastThis: ThisParameterType<T> | null = null; let result: ReturnType<T> | undefined; let lastCallTime: number | null = null; const later = (): void => { const last = lastCallTime !== null ? Date.now() - lastCallTime : 0; if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); } else { timeout = null; if (!immediate) { if (lastArgs !== null && lastThis !== null) { result = func.apply(lastThis, lastArgs); lastArgs = lastThis = null; } } } }; const debounced = function ( this: ThisParameterType<T>, ...args: Parameters<T> ): ReturnType<T> | undefined { lastArgs = args; lastThis = this; lastCallTime = Date.now(); const callNow = immediate && timeout === null; if (!timeout) { timeout = setTimeout(later, wait); } if (callNow) { result = func.apply(this, args); lastArgs = lastThis = null; } return result; }; debounced.cancel = (): void => { if (timeout !== null) { clearTimeout(timeout); timeout = null; lastArgs = lastThis = null; lastCallTime = null; } }; debounced.flush = (): ReturnType<T> | undefined => { if (timeout !== null) { clearTimeout(timeout); timeout = null; if (!immediate) { if (lastArgs !== null && lastThis !== null) { result = func.apply(lastThis, lastArgs); lastArgs = lastThis = null; } } } return result; }; return debounced; }