fix(chat): repair search result sender info

This commit is contained in:
2977094657
2026-03-16 10:17:40 +08:00
parent 1f676254a9
commit 66a2b3224f
4 changed files with 740 additions and 148 deletions

View File

@@ -3,9 +3,11 @@
export class AvatarLoadQueue {
private queue: Array<{ url: string; resolve: () => void; reject: (error: Error) => void }> = []
private loading = new Map<string, Promise<void>>()
private failed = new Map<string, number>()
private activeCount = 0
private readonly maxConcurrent = 3
private readonly delayBetweenBatches = 10
private readonly failedTtlMs = 10 * 60 * 1000
private static instance: AvatarLoadQueue
@@ -18,6 +20,9 @@ export class AvatarLoadQueue {
async enqueue(url: string): Promise<void> {
if (!url) return Promise.resolve()
if (this.hasFailed(url)) {
return Promise.reject(new Error(`Failed: ${url}`))
}
// 核心修复:防止重复并发请求同一个 URL
const existingPromise = this.loading.get(url)
@@ -31,13 +36,40 @@ export class AvatarLoadQueue {
})
this.loading.set(url, loadPromise)
loadPromise.finally(() => {
this.loading.delete(url)
})
void loadPromise.then(
() => {
this.loading.delete(url)
this.clearFailed(url)
},
() => {
this.loading.delete(url)
}
)
return loadPromise
}
hasFailed(url: string): boolean {
if (!url) return false
const failedAt = this.failed.get(url)
if (!failedAt) return false
if (Date.now() - failedAt > this.failedTtlMs) {
this.failed.delete(url)
return false
}
return true
}
markFailed(url: string) {
if (!url) return
this.failed.set(url, Date.now())
}
clearFailed(url: string) {
if (!url) return
this.failed.delete(url)
}
private async processQueue() {
if (this.activeCount >= this.maxConcurrent || this.queue.length === 0) {
return
@@ -49,13 +81,16 @@ export class AvatarLoadQueue {
this.activeCount++
const img = new Image()
img.referrerPolicy = 'no-referrer'
img.onload = () => {
this.activeCount--
this.clearFailed(task.url)
task.resolve()
setTimeout(() => this.processQueue(), this.delayBetweenBatches)
}
img.onerror = () => {
this.activeCount--
this.markFailed(task.url)
task.reject(new Error(`Failed: ${task.url}`))
setTimeout(() => this.processQueue(), this.delayBetweenBatches)
}
@@ -67,6 +102,7 @@ export class AvatarLoadQueue {
clear() {
this.queue = []
this.loading.clear()
this.failed.clear()
this.activeCount = 0
}
}