export class DebouncePublisher<T> { private last_event_time = Date.now(); private unpublished_data: T | undefined; private interval_id: number | undefined; constructor( private readonly publisher: (data: T) => void | Promise<void>, private readonly debounce_ms = 100, ) {} public start() { if (typeof this.interval_id !== "undefined") { return; } this.interval_id = setInterval( () => this.debounce_publish(), this.debounce_ms, ); } public stop() { if (this.interval_id === null) { return; } clearInterval(this.interval_id); delete this.interval_id; } public update(data: T) { this.unpublished_data = data; this.debounce_publish(); } private debounce_publish() { if ( Date.now() - this.last_event_time < this.debounce_ms || typeof this.unpublished_data === "undefined" ) { return; } this.last_event_time = Date.now(); this.publisher(this.unpublished_data); this.unpublished_data = undefined; } }