-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEventEmitter.js
169 lines (143 loc) · 4.14 KB
/
EventEmitter.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
Event Emitter
an event emitter is responsible for managing a set of listeners and publishing events to them when it is told such events happened
used in async event driven architecture
API:
addListener
removeListener
removeAllListeners
emit
once
listeners
http://learnjswith.me/build-an-event-emitter-in-javascript/
*/
class Emitter {
constructor () {
this.events = {};
}
isValidEvent(eventName) {
const events = this.events;
return events.hasOwnProperty(eventName) && Array.isArray(events[eventName]);
}
/**
* Adds a listener to be invoked when events of the specified type are emitted.
*
* @param {string} eventName Name of the event to listen to
* @param {function} callback Function to invoke when the specified event is emitted
**/
addListener(eventName, callback) {
const events = this.events;
if (typeof callback === 'function') {
if (this.isValidEvent(eventName)) {
events[eventName].push(callback);
} else {
events[eventName] = [callback];
}
}
}
/**
* Alias to addListener
**/
on(eventName, callback) {
this.addListener(eventName, callback);
}
/**
* Emits an event of the given type with the given data. All handlers of that particular type will be notified.
*
* @param {string} eventName Name of the event to emit
* @param {*} Arbitrary arguments to be passed to each
* registered listener
*
* @example
* emitter.addListener('someEvent', (message) => {
* console.log(message)
* })
*
* emitter.emit('someEvent', 'hello') // logs 'hello'
*/
emit(eventName, ...args) {
const events = this.events
if (this.isValidEvent(eventName)) {
// create a shallow copy
let listeners = [...events[eventName]];
listeners.forEach((listener) => {
if (listener) {
listener.apply(this, args);
}
});
}
}
/**
* Removes a registered listener from the emitter.
*
* @param {string} event Name of the event listening to
* @param {function} callback Function to remove
*/
removeListener(eventName, callback) {
const events = this.events;
if (this.isValidEvent(eventName)) {
const callbacks = events[eventName];
const stringifedTargetCallback = callback.toString();
callbacks.forEach((callback, idx) => {
if (callback.toString() === stringifedTargetCallback) {
events[eventName].splice(idx, 1);
}
});
}
}
/**
* Removes all of the registered listeners.
*
* @param {string} eventName Name of the event to remove listeners from
*/
removeAllListeners(eventName) {
const events = this.events
if (events.hasOwnProperty(eventName)) {
events[eventName] = []
}
}
/**
* Much like addListener, except the listener is removed after being invoked.
*
* @param {string} eventName Name of the event to listen to
* @param {function} listener Function to invoke only once when the given event is emitted
*/
once(eventName, callback) {
const emitter = this;
emitter.on(eventName, function listenerWrapper () {
callback.apply(emitter, arguments);
emitter.removeListener(eventName, listenerWrapper)
})
}
/**
* Returns an array of listeners that are currently registered for the given
* event.
*
* @param {string} eventName Name of the event to query
* @return {array}
*/
listeners(eventName) {
return this.events.hasOwnProperty(eventName)
? this.events[eventName]
: []
}
}
const emitor = new Emitter();
const callback1 = function(x, y) {console.log(x + y)}
const callback2 = function(x, y) {console.log(y + x)}
emitor.addListener('event_1', callback1);
emitor.addListener('event_1', callback2);
//
// console.log('emitor', emitor);
//
// emitor.emit('event_1', ' hello', ' world');
// emitor.removeListener('event_1', callback2);
// emitor.emit('event_1', ' hello', ' world');
// // emitor.removeAllListeners('event_1');
console.log('emitor', emitor);
// emitor.once('event_2', callback1);
emitor.once('event_2', callback1);
emitor.emit('event_2', ' hello', ' world');
emitor.emit('event_2', ' hello', ' world');
emitor.emit('event_2', ' hello', ' world');
console.log('emitor', emitor);