Files
BYW-VoiceHub/app/composables/useRequestDedup.ts
T
Henry_Du 4ce4649aaf
Build VoiceHub FPK / build-fpk (push) Failing after 56m5s
Build and Push Docker Image / build-and-push (push) Canceled after 1h9m35s
初次提交
2026-09-06 08:19:02 +08:00

128 lines
3.1 KiB
TypeScript

import { ref } from 'vue'
interface PendingRequest {
promise: Promise<any>
timestamp: number
}
// 请求去重超时时间
const REQUEST_DEDUP_TIMEOUT = 5000 // 5秒
export const useRequestDedup = () => {
// 正在进行的请求(用于去重)
const pendingRequests = new Map<string, PendingRequest>()
// 生成请求键
const generateRequestKey = (type: string, params?: Record<string, any>): 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 <T>(
type: string,
requestFn: () => Promise<T>,
params?: Record<string, any>,
force = false
): Promise<T> => {
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<string, number>
}
}
return {
// 核心去重方法
dedupedRequest,
// 管理方法
clearAllPendingRequests,
cleanupPendingRequests,
// 工具方法
generateRequestKey,
getPendingStats
}
}
// 全局去重实例
let globalDedupInstance: ReturnType<typeof useRequestDedup> | null = null
export const getGlobalDedup = () => {
if (!globalDedupInstance) {
globalDedupInstance = useRequestDedup()
}
return globalDedupInstance
}