-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathevent-bus.js
82 lines (76 loc) · 2.69 KB
/
event-bus.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/**
* https://en.wikipedia.org/wiki/Event-driven_architecture#JavaScript
* https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
* https://developer.mozilla.org/en-US/docs/Web/API/Event
* https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#the_event_listener_callback
* https://nodejs.org/api/events.html#class-eventemitter
*/
class EventBus {
#listeners = new Map();
// TODO: add meta and additional functionalities
/*
prependListener(): listener ordering
bool isOnce = false: run the handler once and remove it?
dispatch meta events?
ListenerAdded
ListenerRemoved
EventDispatched
*/
addListener(eventName, eventHandler, isOnce = false) {
if (typeof eventHandler !== "function") {
let eventNameString;
if (typeof eventName == "string") {
eventNameString = `"${eventName}"`;
} else if (eventName instanceof Array) {
eventNameString = "[" + eventName.map(en => `"${en}"`) + "]";
}
throw new TypeError(`The event handler (for ${eventNameString}) must be a function.`);
}
if (typeof eventName == "string") {
let handlers = this.#listeners.get(eventName);
if (!handlers) {
handlers = new Set();
this.#listeners.set(eventName, handlers);
}
if (isOnce) {
const onceHandler = (...args) => {
this.removeListener(eventName, onceHandler);
eventHandler.apply(null, args);
};
handlers.add(onceHandler);
} else {
handlers.add(eventHandler);
}
}
else if (eventName instanceof Array) {
for (let event of eventName) {
this.addListener(event, eventHandler, isOnce);
}
}
return this;
}
removeListener(eventName, eventHandler) {
if (!arguments.length) {
this.#listeners.clear();
} else if (arguments.length === 1) {
this.#listeners.delete(eventName);
} else {
const handlers = this.#listeners.get(eventName);
if (handlers) {
handlers.delete(eventHandler);
}
}
return this;
}
dispatch(eventName, ...args) {
const handlers = this.#listeners.get(eventName);
if (handlers) {
let e = {name : eventName};
args.unshift(e);
for (let handler of handlers) {
handler.apply(this, args);
}
}
return this;
}
}