import { ref } from 'vue' interface PendingRequest { promise: Promise timestamp: number } // 请求去重超时时间 const REQUEST_DEDUP_TIMEOUT = 5000 // 5秒 export const useRequestDedup = () => { // 正在进行的请求(用于去重) const pendingRequests = new Map() // 生成请求键 const generateRequestKey = (type: string, params?: Record): string => { if (!params || Object.keys(params).length === 0) { return type } const sortedParams = Object.keys(params) .sort() .map((key) => `${key}=${params[key]}`) .join('&') return `${type}?${sortedParams}` } // 清理过期的请求 const cleanupPendingRequests = (): void => { const now = Date.now() const keysToDelete: string[] = [] pendingRequests.forEach((request, key) => { if (now - request.timestamp > REQUEST_DEDUP_TIMEOUT) { keysToDelete.push(key) } }) keysToDelete.forEach((key) => pendingRequests.delete(key)) } // 带去重的请求函数 const dedupedRequest = async ( type: string, requestFn: () => Promise, params?: Record, force = false ): Promise => { const requestKey = generateRequestKey(type, params) // 清理过期的请求 cleanupPendingRequests() if (force) { // 强制刷新时,如果有旧的请求正在进行,我们可以选择覆盖或者只是新开一个不存入 pending 的请求。 // 为保证拿到最新数据并避免干扰其他 pending 请求,我们直接执行并不保存到 pendingRequests。 return await requestFn() } // 检查是否有相同的请求正在进行 const pendingRequest = pendingRequests.get(requestKey) if (pendingRequest) { try { return await pendingRequest.promise } catch (error) { // 如果请求失败,移除pending状态 pendingRequests.delete(requestKey) throw error } } // 创建新的请求 const promise = requestFn() pendingRequests.set(requestKey, { promise, timestamp: Date.now() }) try { const data = await promise // 移除pending状态 pendingRequests.delete(requestKey) return data } catch (error) { // 请求失败时移除pending状态 pendingRequests.delete(requestKey) throw error } } // 清除所有pending请求 const clearAllPendingRequests = (): void => { pendingRequests.clear() } // 获取pending请求统计 const getPendingStats = () => { return { totalPendingRequests: pendingRequests.size, pendingByType: {} as Record } } return { // 核心去重方法 dedupedRequest, // 管理方法 clearAllPendingRequests, cleanupPendingRequests, // 工具方法 generateRequestKey, getPendingStats } } // 全局去重实例 let globalDedupInstance: ReturnType | null = null export const getGlobalDedup = () => { if (!globalDedupInstance) { globalDedupInstance = useRequestDedup() } return globalDedupInstance }