自定义事件系统
下面是一个简单的自定义事件系统,内部提供了(比较)完善的类型推导。 继承使用或者直接使用都行。
代码实现(Typescript / JavaScript)
type InputParams< Fn> = Fn extends ( ( ... args: infer P ) => any ) ? P : never [ ]
type ReturnParams< Fn> = Fn extends ( ( ... args: any [ ] ) => infer P ) ? P : never [ ]
export class AbstractEvent< EListener> {
protected readonly _eventHandlers = new Map< keyof EListener, Set< EListener[ keyof EListener] >> ( ) ;
protected beforeDispatch < T extends keyof EListener> ( type : T , args: InputParams< EListener[ T ] > ) : InputParams< EListener[ T ] > {
return args;
}
dispatch < T extends keyof EListener> ( type : T , ... args: InputParams< EListener[ T ] > ) : ReturnParams< EListener[ T ] > [ ] | undefined {
let set = this . _eventHandlers. get ( type ) ;
if ( set ) {
const deleteSet: typeof set = new Set ( ) ;
const returns: any [ ] = [ ] ;
let returnValue: any ;
args = this . beforeDispatch ( type , args) ;
for ( let listener of set ) {
if ( typeof listener === 'function' ) {
returnValue = listener ( ... args) ;
if ( returnValue === 'remove-listener' ) deleteSet. add ( listener) ;
else returns. push ( returnValue) ;
} else console . error ( 'EventController.dispatch listener is not a function' ) ;
}
if ( deleteSet. size > 0 ) {
for ( let listener of deleteSet) set . delete ( listener) ;
if ( set . size === 0 ) this . _eventHandlers. delete ( type ) ;
}
this . afterDispatch ( type , args) ;
return returns as any ;
} else return undefined ;
}
protected afterDispatch < T extends keyof EListener> ( type : T , args: InputParams< EListener[ T ] > ) : void { }
protected beforeAddListener < T extends keyof EListener> ( type : T , handler: EListener[ T ] ) : void { }
addListener < T extends keyof EListener> ( type : T , handler: EListener[ T ] ) : void {
let set = this . _eventHandlers. get ( type ) ;
if ( ! set ) this . _eventHandlers. set ( type , set = new Set< EListener[ keyof EListener] > ( ) ) ;
this . beforeAddListener ( type , handler) ;
set . add ( handler) ;
this . afterAddListener ( type , handler) ;
}
protected afterAddListener < T extends keyof EListener> ( type : T , handler: EListener[ T ] ) : void { }
protected beforeRemoveListener < T extends keyof EListener> ( type : T , handler: EListener[ T ] ) : void { }
removeListener < T extends keyof EListener> ( type : T , handler: EListener[ T ] ) : void {
let set = this . _eventHandlers. get ( type ) ;
if ( set ) {
this . beforeRemoveListener ( type , handler) ;
set . delete ( handler) ;
if ( set . size === 0 ) this . _eventHandlers. delete ( type ) ;
this . afterRemoveListener ( type , handler) ;
}
}
protected afterRemoveListener < T extends keyof EListener> ( type : T , handler: EListener[ T ] ) : void { }
}
使用指南
使用时需要传入一个泛型来辅助类型推到,该泛型应该是一个字典类型接口,demo如下所示:
interface MeSqlEvent {
Before_connect : ( self: MySQL) => void
Error_connect : ( self: MySQL) => void
After_connect : ( self: MySQL) => void
Before_disConnect : ( self: MySQL) => void
Error_disConnect : ( self: MySQL) => void
After_disConnect : ( self: MySQL) => void
Change_database : ( self: MySQL, database: string ) => void
}
接口的key是事件名称,value是事件所对应的listener函数接口,AbstractEvent会通过该泛型实现比较强大的类型推导。 使用时推荐继承:
class MySQL extends AbstractEvent< MeSqlEvent> {
}