import { IMutableReactor , IReactor , Reactor } from './Reactor' ; import { EventListener , RegisteredEventListener } from './EventListener' ; import { isPresent } from 'polar-shared/src/Preconditions' ; /**
 * A reactor that allows dispatchEvents to be queue'd up until the first
 * listener is added for an event at which point the existing values are
 * drained.
 */ export class QueuedReactor < V > implements IReactor < V > , IMutableReactor < V > { private readonly delegate : Reactor < V > ; private readonly queue : { [ name ] : V [ ] ; } = { } ; constructor ( delegate = new Reactor < V > ( ) ) { this . delegate = delegate ; } public addEventListener ( eventName , eventListener ) { this . delegate . addEventListener ( eventName , eventListener ) ; if ( this . hasEnqueued ( eventName ) ) { for ( const current of this . clearEnqueued ( eventName ) ) { this . delegate . dispatchEvent ( eventName , current ) ; } } const release = ( ) => { this . removeEventListener ( eventName , eventListener ) ; } ; return { eventListener , release } ; } public once ( eventName ) { return new Promise < V > ( ( resolve => { const listener = ( event ) => { resolve ( event ) ; this . removeEventListener ( eventName , listener ) ; } ; this . addEventListener ( eventName , listener ) ; } ) ) ; } public dispatchEvent ( eventName , value ) { if ( this . delegate . hasEventListeners ( eventName ) ) { this . delegate . dispatchEvent ( eventName , value ) ; } else { this . enqueue ( eventName , value ) ; } } public getEventListeners ( eventName ) { return this . delegate . getEventListeners ( eventName ) ; } public hasEventListeners ( eventName ) { return this . delegate . hasEventListeners ( eventName ) ; } public registerEvent ( eventName ) { this . delegate . registerEvent ( eventName ) ; return this ; } public hasRegisteredEvent ( eventName ) { return this . delegate . hasRegisteredEvent ( eventName ) ; } public clearEvent ( eventName ) { this . delegate . clearEvent ( eventName ) ; } public removeEventListener ( eventName , listener ) { return this . delegate . removeEventListener ( eventName , listener ) ; } public size ( eventName ) { return this . delegate . size ( eventName ) ; } private enqueue ( eventName , value ) { if ( ! isPresent ( this . queue [ eventName ] ) ) { this . queue [ eventName ] = [ ] ; } this . queue [ eventName ] . push ( value ) ; return this ; } /**
     * Clear the enqueued queue for this event name and return the data there
     * previously.
     */ private clearEnqueued ( eventName ) { if ( isPresent ( this . queue [ eventName ] ) ) { const data = this . queue [ eventName ] ; delete this . queue [ eventName ] ; return data ; } else { return [ ] ; } } private hasEnqueued ( eventName ) { return isPresent ( this . queue [ eventName ] ) && this . queue [ eventName ] . length > 0 ; } }