import { isPresent , Preconditions } from 'polar-shared/src/Preconditions' ; import { Event } from './Event' ; import { EventListener , RegisteredEventListener } from './EventListener' ; import { Logger } from 'polar-shared/src/logger/Logger' ; import { ISimpleReactor } from './SimpleReactor' ; const log = Logger . create ( ) ; export class Reactor < V > implements IReactor < V > { private readonly events : { [ name ] : Event < V > ; } = { } ; public registerEvent ( eventName ) { Preconditions . assertNotNull ( eventName , "eventName" ) ; if ( isPresent ( this . events [ eventName ] ) ) { return this ; } const event = new Event < V > ( eventName ) ; this . events [ eventName ] = event ; return this ; } public hasRegisteredEvent ( eventName ) { return isPresent ( this . events [ eventName ] ) ; } public eventNames ( ) { return Object . keys ( this . events ) ; } public clearEvent ( eventName ) { const event = new Event < V > ( eventName ) ; this . events [ eventName ] = event ; return this ; } public size ( eventName ) { if ( this . events [ eventName ] ) { return this . events [ eventName ] . size ( ) ; } return 0 ; } param eventName param value return { Reactor } public dispatchEvent ( eventName , value ) { Preconditions . assertNotNull ( eventName , "eventName" ) ; const event = this . events [ eventName ] ; if ( ! event ) { throw new Error ( "No events for event name: " + eventName ) ; } event . getListeners ( ) . forEach ( ( listener ) => { try { listener ( value ) ; } catch ( e ) { log . error ( "listener generated unhandled exception: " , e ) ; } } ) ; return this ; } public addEventListener ( eventName , eventListener ) { Preconditions . assertNotNull ( eventName , "eventName" ) ; if ( typeof eventListener !== "function" ) { throw new Error ( "listener is not a function: " + typeof eventListener ) ; } if ( this . events [ eventName ] === undefined ) { throw new Error ( "No registered event for event name: " + eventName ) ; } this . events [ eventName ] . registerListener ( eventListener ) ; const release = ( ) => { this . removeEventListener ( eventName , eventListener ) ; } ; return { eventListener , release } ; } public removeEventListener ( eventName , listener ) { if ( this . events [ eventName ] ) { return this . events [ eventName ] . removeListener ( listener ) ; } return false ; } public once ( eventName ) { return new Promise < V > ( ( resolve => { const listener = ( event ) => { resolve ( event ) ; this . removeEventListener ( eventName , listener ) ; } ; this . addEventListener ( eventName , listener ) ; } ) ) ; } param eventName { String } public getEventListeners ( eventName ) { Preconditions . assertNotNull ( eventName , "eventName" ) ; return this . events [ eventName ] . getListeners ( ) ; } public hasEventListeners ( eventName ) { return this . hasRegisteredEvent ( eventName ) && this . events [ eventName ] . hasListeners ( ) ; } } export interface IReactor < V > { once ( eventName ) : Promise < V > ; addEventListener ( eventName , listener ) : RegisteredEventListener < V > ; dispatchEvent ( eventName , value ) : void ; hasRegisteredEvent ( eventName ) : boolean ; hasEventListeners ( eventName ) : boolean ; registerEvent ( eventName ) : IReactor < V > ; size ( eventName ) : number ; } export interface IMutableReactor < V > extends IReactor < V > { clearEvent ( eventName ) : void ; removeEventListener ( eventName , listener ) : boolean ; getEventListeners ( eventName ) : Array < EventListener < V > > ; size ( eventName ) : number ; } export interface INamedEventDispatcher < V > extends IReactor < V > { }