Last active
April 2, 2022 07:19
-
-
Save hamzakaya/e8b6bb4cc4153b2aa9ad6404b0bcf961 to your computer and use it in GitHub Desktop.
Fire Event (pub/sub/unsub)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type EventType = string | symbol | |
type Handler<T = unknown> = (event: T) => void | |
type OtherHandler<T = Record<string, unknown>> = ( | |
type: keyof T, | |
event: T[keyof T], | |
) => void | |
type EventHandlerList<T = unknown> = Array<Handler<T>> | |
type OtherHandlerList<T = Record<string, unknown>> = Array<OtherHandler<T>> | |
type EventHandlerMap<Events extends Record<EventType, unknown>> = Map< | |
keyof Events | '*', | |
EventHandlerList<Events[keyof Events]> | OtherHandlerList<Events> | |
> | |
interface Emitter<Events extends Record<EventType, unknown>> { | |
all: EventHandlerMap<Events> | |
sub<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void | |
sub(type: '*', handler: OtherHandler<Events>): void | |
unsub<Key extends keyof Events>( | |
type: Key, | |
handler?: Handler<Events[Key]>, | |
): void | |
unsub(type: '*', handler: OtherHandler<Events>): void | |
pub<Key extends keyof Events>(type: Key, event: Events[Key]): void | |
pub<Key extends keyof Events>( | |
type: undefined extends Events[Key] ? Key : never, | |
): void | |
} | |
export default function fireEvent<Events extends Record<EventType, unknown>>( | |
all?: EventHandlerMap<Events>, | |
): Emitter<Events> { | |
type DynamicEventHandler = | |
| Handler<Events[keyof Events]> | |
| OtherHandler<Events> | |
all = all || new Map() | |
return { | |
all, | |
pub<Key extends keyof Events>(type: Key, evt?: Events[Key]) { | |
let handlers = all!.get(type) | |
if (handlers) { | |
;(handlers as EventHandlerList<Events[keyof Events]>) | |
.slice() | |
.map((handler) => handler(evt!)) | |
} | |
handlers = all!.get('*') | |
if (handlers) { | |
;(handlers as OtherHandlerList<Events>) | |
.slice() | |
.map((handler) => handler(type, evt!)) | |
} | |
}, | |
sub<Key extends keyof Events>(type: Key, handler: DynamicEventHandler) { | |
const handlers: Array<DynamicEventHandler> | undefined = all!.get(type) | |
if (handlers) handlers.push(handler) | |
else all!.set(type, [handler] as EventHandlerList<Events[keyof Events]>) | |
}, | |
unsub<Key extends keyof Events>(type: Key, handler?: DynamicEventHandler) { | |
const handlers: Array<DynamicEventHandler> | undefined = all!.get(type) | |
if (handlers) { | |
if (handler) handlers.splice(handlers.indexOf(handler) >>> 0, 1) | |
else all!.set(type, []) | |
} | |
}, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment