mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-11 22:06:17 -08:00
70 lines
1.4 KiB
TypeScript
70 lines
1.4 KiB
TypeScript
export function createFrameScheduler(draw: (valid: () => boolean) => Promise<void>, active: () => boolean) {
|
|
let running = false
|
|
let closed = false
|
|
let busy = false
|
|
let pending = false
|
|
let generation = 0
|
|
let frame: number | null = null
|
|
|
|
function cancel(): void {
|
|
if (frame !== null)
|
|
cancelAnimationFrame(frame)
|
|
frame = null
|
|
}
|
|
|
|
function drain(): void {
|
|
if (busy || closed || !active())
|
|
return
|
|
if (pending) {
|
|
pending = false
|
|
busy = true
|
|
const version = generation
|
|
const valid = () => !closed && active() && generation === version
|
|
const complete = () => {
|
|
busy = false
|
|
drain()
|
|
}
|
|
// An observer throwing must not leave the scheduler busy or reject unhandled.
|
|
void draw(valid).then(complete, complete)
|
|
}
|
|
else if (running && frame === null) {
|
|
frame = requestAnimationFrame(() => {
|
|
frame = null
|
|
pending = true
|
|
drain()
|
|
})
|
|
}
|
|
}
|
|
|
|
function request(): void {
|
|
if (closed || !active())
|
|
return
|
|
generation++
|
|
pending = true
|
|
cancel()
|
|
drain()
|
|
}
|
|
|
|
function stop(): void {
|
|
running = false
|
|
pending = false
|
|
generation++
|
|
cancel()
|
|
}
|
|
|
|
return {
|
|
request,
|
|
start() {
|
|
if (running || closed || !active())
|
|
return
|
|
running = true
|
|
request()
|
|
},
|
|
stop,
|
|
destroy() {
|
|
closed = true
|
|
stop()
|
|
},
|
|
}
|
|
}
|