🚧 Optimize
This commit is contained in:
111
frontend/src/common/utils/debounce.ts
Normal file
111
frontend/src/common/utils/debounce.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 防抖函数工具类
|
||||
* 用于限制函数的执行频率,在指定时间内只执行最后一次调用
|
||||
*/
|
||||
|
||||
export interface DebounceOptions {
|
||||
/** 延迟时间(毫秒),默认 300ms */
|
||||
delay?: number;
|
||||
/** 是否立即执行第一次调用,默认 false */
|
||||
immediate?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建防抖函数
|
||||
* @param fn 要防抖的函数
|
||||
* @param options 防抖选项
|
||||
* @returns 返回防抖后的函数和清理函数
|
||||
*/
|
||||
export function createDebounce<T extends (...args: any[]) => any>(
|
||||
fn: T,
|
||||
options: DebounceOptions = {}
|
||||
): {
|
||||
debouncedFn: T;
|
||||
cancel: () => void;
|
||||
flush: () => void;
|
||||
} {
|
||||
const { delay = 300, immediate = false } = options;
|
||||
let timeoutId: number | null = null;
|
||||
let lastArgs: Parameters<T> | null = null;
|
||||
let lastThis: any = null;
|
||||
|
||||
const debouncedFn = function (this: any, ...args: Parameters<T>) {
|
||||
lastArgs = args;
|
||||
lastThis = this;
|
||||
|
||||
const callNow = immediate && !timeoutId;
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
timeoutId = window.setTimeout(() => {
|
||||
timeoutId = null;
|
||||
if (!immediate && lastArgs) {
|
||||
fn.apply(lastThis, lastArgs);
|
||||
}
|
||||
}, delay);
|
||||
|
||||
if (callNow) {
|
||||
return fn.apply(this, args);
|
||||
}
|
||||
} as T;
|
||||
|
||||
const cancel = () => {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
}
|
||||
lastArgs = null;
|
||||
lastThis = null;
|
||||
};
|
||||
|
||||
const flush = () => {
|
||||
if (timeoutId && lastArgs) {
|
||||
clearTimeout(timeoutId);
|
||||
fn.apply(lastThis, lastArgs);
|
||||
timeoutId = null;
|
||||
lastArgs = null;
|
||||
lastThis = null;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
debouncedFn,
|
||||
cancel,
|
||||
flush
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 节流函数
|
||||
* 在指定时间内最多执行一次函数
|
||||
* @param fn 要节流的函数
|
||||
* @param delay 节流时间间隔(毫秒)
|
||||
* @returns 节流后的函数
|
||||
*/
|
||||
export function throttle<T extends (...args: any[]) => any>(
|
||||
fn: T,
|
||||
delay: number = 300
|
||||
): T {
|
||||
let lastExecTime = 0;
|
||||
let timeoutId: number | null = null;
|
||||
|
||||
return ((...args: Parameters<T>) => {
|
||||
const now = Date.now();
|
||||
|
||||
if (now - lastExecTime >= delay) {
|
||||
lastExecTime = now;
|
||||
fn(...args);
|
||||
} else {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
timeoutId = window.setTimeout(() => {
|
||||
lastExecTime = Date.now();
|
||||
fn(...args);
|
||||
}, delay - (now - lastExecTime));
|
||||
}
|
||||
}) as T;
|
||||
}
|
||||
162
frontend/src/common/utils/timerUtils.ts
Normal file
162
frontend/src/common/utils/timerUtils.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* 定时器管理工具类
|
||||
* 提供安全的定时器创建、清理和管理功能
|
||||
*/
|
||||
|
||||
/**
|
||||
* 定时器管理器接口
|
||||
*/
|
||||
export interface TimerManager {
|
||||
/** 当前定时器 ID */
|
||||
readonly timerId: number | null;
|
||||
/** 清除定时器 */
|
||||
clear(): void;
|
||||
/** 设置定时器 */
|
||||
set(callback: () => void, delay: number): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建定时器管理器工厂函数
|
||||
* 提供安全的定时器管理,自动处理清理和重置
|
||||
*
|
||||
* @returns 定时器管理器实例
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const timer = createTimerManager();
|
||||
*
|
||||
* // 设置定时器
|
||||
* timer.set(() => {
|
||||
* console.log('Timer executed');
|
||||
* }, 1000);
|
||||
*
|
||||
* // 清除定时器
|
||||
* timer.clear();
|
||||
*
|
||||
* // 检查定时器状态
|
||||
* if (timer.timerId !== null) {
|
||||
* console.log('Timer is running');
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export const createTimerManager = (): TimerManager => {
|
||||
let timerId: number | null = null;
|
||||
|
||||
return {
|
||||
get timerId() {
|
||||
return timerId;
|
||||
},
|
||||
|
||||
clear() {
|
||||
if (timerId !== null) {
|
||||
window.clearTimeout(timerId);
|
||||
timerId = null;
|
||||
}
|
||||
},
|
||||
|
||||
set(callback: () => void, delay: number) {
|
||||
// 先清除现有定时器
|
||||
this.clear();
|
||||
|
||||
// 设置新定时器
|
||||
timerId = window.setTimeout(() => {
|
||||
callback();
|
||||
timerId = null; // 执行完成后自动重置
|
||||
}, delay);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建带有自动清理功能的定时器
|
||||
* 适用于需要在组件卸载时自动清理的场景
|
||||
*
|
||||
* @param onCleanup 清理回调函数,通常在 onScopeDispose 或 onUnmounted 中调用
|
||||
* @returns 定时器管理器实例
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { onScopeDispose } from 'vue';
|
||||
*
|
||||
* const timer = createAutoCleanupTimer(() => {
|
||||
* // 组件卸载时自动清理
|
||||
* });
|
||||
*
|
||||
* onScopeDispose(() => {
|
||||
* timer.clear();
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export const createAutoCleanupTimer = (onCleanup?: () => void): TimerManager => {
|
||||
const timer = createTimerManager();
|
||||
|
||||
// 如果提供了清理回调,则包装 clear 方法
|
||||
if (onCleanup) {
|
||||
const originalClear = timer.clear.bind(timer);
|
||||
timer.clear = () => {
|
||||
originalClear();
|
||||
onCleanup();
|
||||
};
|
||||
}
|
||||
|
||||
return timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* 延迟执行工具函数
|
||||
* 简化的 Promise 版本延迟执行
|
||||
*
|
||||
* @param delay 延迟时间(毫秒)
|
||||
* @returns Promise
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await delay(1000); // 延迟 1 秒
|
||||
* console.log('1 second later');
|
||||
* ```
|
||||
*/
|
||||
export const delay = (delay: number): Promise<void> => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, delay);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建可取消的延迟 Promise
|
||||
*
|
||||
* @param delay 延迟时间(毫秒)
|
||||
* @returns 包含 promise 和 cancel 方法的对象
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const { promise, cancel } = createCancelableDelay(1000);
|
||||
*
|
||||
* promise
|
||||
* .then(() => console.log('Executed'))
|
||||
* .catch(() => console.log('Cancelled'));
|
||||
*
|
||||
* // 取消延迟
|
||||
* cancel();
|
||||
* ```
|
||||
*/
|
||||
export const createCancelableDelay = (delay: number) => {
|
||||
let timeoutId: number;
|
||||
let cancelled = false;
|
||||
|
||||
const promise = new Promise<void>((resolve, reject) => {
|
||||
timeoutId = window.setTimeout(() => {
|
||||
if (!cancelled) {
|
||||
resolve();
|
||||
}
|
||||
}, delay);
|
||||
});
|
||||
|
||||
const cancel = () => {
|
||||
cancelled = true;
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
};
|
||||
|
||||
return { promise, cancel };
|
||||
};
|
||||
Reference in New Issue
Block a user