Event
One problem of callbacks is that is a one to one pattern, it gets a little complicated when multiple participants want to get called. But that's still possible:
const listenForClick = (element, callback) => {
const onclick = element.onclick
element.onclick = ev => {
onclick?.(ev) // or: onclick && onclick(ev)
callback(ev)
}
}
Everytime one needs to listen for the click event, call this function
listenForClick(document.body, ev => console.log(ev))
What a brilliant solution!
But there can be better ones, like event:
document.body.addEventListener('click', ev => console.log(ev))
Here the event is 'click', the listener is the function ev => console.log(ev).
You can add multiple listeners, there won't be any conflict like callbacks had.
And event better, you can remove them later.
const log = ev => console.log(ev)
document.body.addEventListener('click', log)
// to remove
document.body.removeEventListener('click', log)
implement event dispatcher using callbacks
type Listener<T> = (data?: T) => void
class EventEmitter<T> {
private listeners: { [event: string]: Array<Listener<T>> } = {}
on(event: string, listener: Listener<T>) {
if (!this.listeners[event]) {
this.listeners[event] = []
}
this.listeners[event].push(listener)
}
off(event: string, listener: Listener<T>) {
if (this.listeners[event]) {
this.listeners[event] = this.listeners[event].filter(x => x !== listener)
}
}
emit(event: string, data?: T) {
this.listeners[event]?.forEach(listener => listener(data))
}
}