优化后台业务

This commit is contained in:
super
2026-04-30 11:36:58 +08:00
parent 9c16c9c589
commit c6ecfb5b77
48 changed files with 1211 additions and 2391 deletions

View File

@@ -0,0 +1,113 @@
type TimerKind = 'timeout' | 'interval'
type TimerCancel = () => void
interface TimerEntry {
id: number
kind: TimerKind
category: string
cancel?: TimerCancel
}
const timerBuckets = new Map<string, Map<number, TimerEntry>>()
function bucketOf(category: string) {
let bucket = timerBuckets.get(category)
if (!bucket) {
bucket = new Map<number, TimerEntry>()
timerBuckets.set(category, bucket)
}
return bucket
}
function removeTimer(category: string, id: number) {
const bucket = timerBuckets.get(category)
if (!bucket) return
bucket.delete(id)
if (!bucket.size) timerBuckets.delete(category)
}
export function setCategorizedTimeout(category: string, handler: () => void, delayMs: number) {
const id = window.setTimeout(() => {
removeTimer(category, id)
handler()
}, delayMs)
bucketOf(category).set(id, { id, kind: 'timeout', category })
return id
}
export function setCategorizedInterval(category: string, handler: () => void, delayMs: number) {
const id = window.setInterval(handler, delayMs)
bucketOf(category).set(id, { id, kind: 'interval', category })
return id
}
export function clearCategorizedTimer(category: string, id: number | null | undefined) {
if (id == null) return
const bucket = timerBuckets.get(category)
const entry = bucket?.get(id)
if (entry?.kind === 'interval') window.clearInterval(id)
else window.clearTimeout(id)
entry?.cancel?.()
removeTimer(category, id)
}
export function clearCategorizedTimers(category: string) {
const bucket = timerBuckets.get(category)
if (!bucket) return
for (const entry of bucket.values()) {
if (entry.kind === 'interval') window.clearInterval(entry.id)
else window.clearTimeout(entry.id)
entry.cancel?.()
}
timerBuckets.delete(category)
}
export function sleepWithCategory(category: string, delayMs: number) {
return new Promise<void>((resolve) => {
const id = window.setTimeout(() => {
removeTimer(category, id)
resolve()
}, delayMs)
bucketOf(category).set(id, { id, kind: 'timeout', category, cancel: resolve })
})
}
export function clearTimerScope(scope: string) {
const prefix = `${scope}:`
for (const category of Array.from(timerBuckets.keys())) {
if (category === scope || category.startsWith(prefix)) {
clearCategorizedTimers(category)
}
}
}
export function createCategorizedTimers(scope: string) {
const key = (category: string) => `${scope}:${category}`
return {
setTimeout(category: string, handler: () => void, delayMs: number) {
return setCategorizedTimeout(key(category), handler, delayMs)
},
setInterval(category: string, handler: () => void, delayMs: number) {
return setCategorizedInterval(key(category), handler, delayMs)
},
clearTimer(category: string, id: number | null | undefined) {
clearCategorizedTimer(key(category), id)
},
clearCategory(category: string) {
clearCategorizedTimers(key(category))
},
clearScope() {
clearTimerScope(scope)
},
sleep(category: string, delayMs: number) {
return sleepWithCategory(key(category), delayMs)
},
}
}
export function getCategorizedTimerStats() {
return Array.from(timerBuckets.entries()).map(([category, bucket]) => ({
category,
count: bucket.size,
}))
}