interface SchedulerOptions { deferEvents : boolean ; } const defaultOptions = { deferEvents : false } ; export class Scheduler { private processingEvent : boolean = false ; private queue : Array < ( ) => void > = [ ] ; private initialized = false ; private options : SchedulerOptions ; constructor ( options ? ) { this . options = { ... defaultOptions , ... options } ; } public initialize ( callback ? ) { this . initialized = true ; if ( callback ) { if ( ! this . options . deferEvents ) { this . schedule ( callback ) ; return ; } this . process ( callback ) ; } this . flushEvents ( ) ; } public schedule ( task ) { if ( ! this . initialized || this . processingEvent ) { this . queue . push ( task ) ; return ; } if ( this . queue . length !== 0 ) { throw new Error ( 'Event queue should be empty when it is not processing events' ) ; } this . process ( task ) ; this . flushEvents ( ) ; } public clear ( ) { this . queue = [ ] ; } private flushEvents ( ) { let nextCallback = this . queue . shift ( ) ; while ( nextCallback ) { this . process ( nextCallback ) ; nextCallback = this . queue . shift ( ) ; } } private process ( callback ) { this . processingEvent = true ; try { callback ( ) ; } catch ( e ) { this . clear ( ) ; throw e ; } finally { this . processingEvent = false ; } } }