12 lines
1.0 KiB
TypeScript
12 lines
1.0 KiB
TypeScript
/** Presentation invalidations only. Commands, history and network work never wait here. */
|
|
export type FrameClock={request(callback:()=>void):unknown;cancel(handle:unknown):void};
|
|
export function createFrameQueue<K>(clock:FrameClock,publish:(dirty:ReadonlySet<K>)=>void){
|
|
let dirty=new Set<K>(),scheduled:{handle?:unknown}|undefined,disposed=false;
|
|
function flush(){if(disposed)return;const pending=scheduled;scheduled=undefined;if(pending)clock.cancel(pending.handle);if(!dirty.size)return;const batch=dirty;dirty=new Set();publish(batch);}
|
|
return Object.freeze({
|
|
invalidate(keys:Iterable<K>){if(disposed)return;for(const key of keys)dirty.add(key);if(!dirty.size||scheduled)return;const pending: {handle?:unknown}={};scheduled=pending;try{pending.handle=clock.request(()=>{if(scheduled!==pending)return;scheduled=undefined;flush();});}catch(error){scheduled=undefined;throw error;}},
|
|
flush,
|
|
dispose(){if(disposed)return;disposed=true;if(scheduled)clock.cancel(scheduled.handle);scheduled=undefined;dirty.clear();},
|
|
});
|
|
}
|