Files
WeFlow/src/utils/AvatarLoadQueue.ts
cc 2e41a03c96 feat: 所有数据解析完全后台进行以解决页面未响应的问题;优化了头像渲染逻辑以提升渲染速度
fix: 修复了虚拟机上无法索引到wxkey的问题;修复图片密钥扫描的问题;修复年度报告错误;修复了年度报告和数据分析中的发送者错误问题;修复了部分页面偶发的未渲染名称问题;修复了头像偶发渲染失败的问题;修复了部分图片无法解密的问题
2026-01-14 22:43:42 +08:00

75 lines
2.1 KiB
TypeScript

// 全局头像加载队列管理器(限制并发,避免卡顿)
export class AvatarLoadQueue {
private queue: Array<{ url: string; resolve: () => void; reject: (error: Error) => void }> = []
private loading = new Map<string, Promise<void>>()
private activeCount = 0
private readonly maxConcurrent = 3
private readonly delayBetweenBatches = 10
private static instance: AvatarLoadQueue
public static getInstance(): AvatarLoadQueue {
if (!AvatarLoadQueue.instance) {
AvatarLoadQueue.instance = new AvatarLoadQueue()
}
return AvatarLoadQueue.instance
}
async enqueue(url: string): Promise<void> {
if (!url) return Promise.resolve()
// 核心修复:防止重复并发请求同一个 URL
const existingPromise = this.loading.get(url)
if (existingPromise) {
return existingPromise
}
const loadPromise = new Promise<void>((resolve, reject) => {
this.queue.push({ url, resolve, reject })
this.processQueue()
})
this.loading.set(url, loadPromise)
loadPromise.finally(() => {
this.loading.delete(url)
})
return loadPromise
}
private async processQueue() {
if (this.activeCount >= this.maxConcurrent || this.queue.length === 0) {
return
}
const task = this.queue.shift()
if (!task) return
this.activeCount++
const img = new Image()
img.onload = () => {
this.activeCount--
task.resolve()
setTimeout(() => this.processQueue(), this.delayBetweenBatches)
}
img.onerror = () => {
this.activeCount--
task.reject(new Error(`Failed: ${task.url}`))
setTimeout(() => this.processQueue(), this.delayBetweenBatches)
}
img.src = task.url
this.processQueue()
}
clear() {
this.queue = []
this.loading.clear()
this.activeCount = 0
}
}
export const avatarLoadQueue = AvatarLoadQueue.getInstance()