43 lines
1.9 KiB
TypeScript
43 lines
1.9 KiB
TypeScript
/** 合并聊天窗口的收发事件;每次同步只接受后端读取的云端消息,不上报客户端正文。 */
|
||
export function createImChatArchiveTrigger(
|
||
syncPage: (params: { diagnosis_id: number; scope: 'current'; sync_token?: string }) => Promise<{
|
||
sync_token?: string; completed: boolean; errors?: string[]
|
||
}>,
|
||
onError: (error: unknown) => void = () => {}
|
||
) {
|
||
const jobs = new Map<number, { again: boolean; promise: Promise<void> }>()
|
||
return (diagnosisId: number): Promise<void> => {
|
||
if (!Number.isInteger(diagnosisId) || diagnosisId <= 0) return Promise.resolve()
|
||
const pending = jobs.get(diagnosisId)
|
||
if (pending) {
|
||
pending.again = true
|
||
return pending.promise
|
||
}
|
||
const job = { again: false, promise: Promise.resolve() }
|
||
jobs.set(diagnosisId, job)
|
||
job.promise = (async () => {
|
||
try {
|
||
do {
|
||
job.again = false
|
||
let token: string | undefined
|
||
for (;;) {
|
||
const result = await syncPage({ diagnosis_id: diagnosisId, scope: 'current', sync_token: token })
|
||
if (result.completed) {
|
||
if (result.errors?.length) throw new Error(result.errors.join(';'))
|
||
break
|
||
}
|
||
if (!result.sync_token) throw new Error('聊天记录同步未返回进度')
|
||
token = result.sync_token
|
||
}
|
||
// 同步期间收到新消息时再追一次,覆盖新消息晚于本轮首页的情况。
|
||
} while (job.again)
|
||
} catch (error) {
|
||
onError(error)
|
||
} finally {
|
||
jobs.delete(diagnosisId)
|
||
}
|
||
})()
|
||
return job.promise
|
||
}
|
||
}
|