@irrelon/emitter 5.0.0 → 5.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +1 -3
- package/.eslintrc.json +35 -18
- package/.prettierignore +9 -0
- package/.prettierrc.yml +9 -0
- package/fixPaths.cjs +183 -0
- package/package.json +31 -24
- package/readme.md +16 -45
- package/src/Emitter.d.ts +190 -0
- package/src/Emitter.js +580 -0
- package/src/Emitter.ts +294 -247
- package/tests/Emitter.test.d.ts +1 -0
- package/tests/Emitter.test.js +267 -309
- package/tests/Emitter.test.ts +335 -0
- package/tsconfig.json +33 -12
- package/tsconfig.tsbuildinfo +1 -0
- package/.babelrc +0 -11
- package/dist/Emitter.d.ts +0 -205
- package/dist/Emitter.js +0 -415
package/src/Emitter.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
The MIT License (MIT)
|
|
3
3
|
|
|
4
4
|
Copyright (c) 2014 Irrelon Software Limited
|
|
5
|
-
|
|
5
|
+
https://www.irrelon.com
|
|
6
6
|
|
|
7
7
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
8
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -25,12 +25,13 @@
|
|
|
25
25
|
Source: https://github.com/irrelon/emitter
|
|
26
26
|
|
|
27
27
|
Changelog:
|
|
28
|
+
Version 5.0.2:
|
|
29
|
+
Removed some unnecessary code, updated to be in step with version
|
|
30
|
+
that is being used in the new version of Isogenic Game Engine.
|
|
31
|
+
Version 5.0.1:
|
|
32
|
+
Further TypeScript updates.
|
|
28
33
|
Version 5.0.0:
|
|
29
|
-
Added
|
|
30
|
-
running.
|
|
31
|
-
Breaking change. When using makeEmitter, prototypeMode is now
|
|
32
|
-
false by default. Simply pass makeEmitter(SomeClass.prototype)
|
|
33
|
-
instead of makeEmitter(SomeClass) to modify a prototype.
|
|
34
|
+
Added TypeScript and prettier, removed babel etc
|
|
34
35
|
Version 4.0.1:
|
|
35
36
|
Updated library to use new ES6 functionality making Overload()
|
|
36
37
|
less useful so it can be removed as a dependency.
|
|
@@ -83,83 +84,62 @@
|
|
|
83
84
|
Version 1.0.0:
|
|
84
85
|
First commit
|
|
85
86
|
*/
|
|
86
|
-
export
|
|
87
|
-
|
|
87
|
+
export enum EventReturnFlag {
|
|
88
|
+
none,
|
|
89
|
+
cancel
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
export
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
export type EventListenerType = (...rest: any[]) => any;
|
|
95
|
-
|
|
96
|
-
export interface InternalEventEmittersType {
|
|
97
|
-
[eventName: string|symbol]: Array<EventEmitterType>
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface EventEmitterType {
|
|
101
|
-
id: string|symbol
|
|
102
|
-
args: any
|
|
92
|
+
export type EventListenerCallback = (...args: any[]) => any | Promise<any>;
|
|
93
|
+
export interface EventStaticEmitterObject {
|
|
94
|
+
id: string;
|
|
95
|
+
args: any[];
|
|
103
96
|
}
|
|
104
97
|
|
|
105
98
|
/**
|
|
106
|
-
*
|
|
107
|
-
* @constructor
|
|
99
|
+
* Creates a new class with the capability to emit events.
|
|
108
100
|
*/
|
|
109
101
|
export class Emitter {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
constructor (obj?: any) {
|
|
118
|
-
this._noEmitDefer = false;
|
|
119
|
-
this._emitting = false;
|
|
120
|
-
this._listeners = {};
|
|
121
|
-
this._emitters = {};
|
|
122
|
-
this._eventRemovalQueue = [];
|
|
123
|
-
|
|
124
|
-
if (obj !== undefined) {
|
|
125
|
-
return makeEmitter(obj);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
102
|
+
_eventsEmitting: boolean = false;
|
|
103
|
+
_eventRemovalQueue: any[] = [];
|
|
104
|
+
_eventListeners?: Record<string, Record<string, EventListenerCallback[]>>;
|
|
105
|
+
_eventStaticEmitters: Record<string, EventStaticEmitterObject[]> = {};
|
|
106
|
+
_eventsAllowDefer: boolean = false;
|
|
107
|
+
_eventsDeferTimeouts: Record<any, number> = {};
|
|
128
108
|
|
|
129
109
|
/**
|
|
130
110
|
* Attach an event listener to the passed event only if the passed
|
|
131
|
-
* id matches the
|
|
132
|
-
* @
|
|
133
|
-
* @
|
|
134
|
-
* @param {
|
|
135
|
-
* @param {*} id The document id to match against.
|
|
136
|
-
* @param {Function} listener The method to call when the event is fired.
|
|
111
|
+
* id matches the id for the event being fired.
|
|
112
|
+
* @param {string} eventName The name of the event to listen for.
|
|
113
|
+
* @param {string} id The id to match against.
|
|
114
|
+
* @param {function} listener The method to call when the event is fired.
|
|
137
115
|
* @returns {Emitter} The emitter instance.
|
|
138
116
|
*/
|
|
139
|
-
_on (
|
|
140
|
-
const
|
|
117
|
+
_on (eventName: string, id: string, listener: EventListenerCallback) {
|
|
118
|
+
const generateTimeout = (emitter: EventStaticEmitterObject) => {
|
|
141
119
|
setTimeout(() => {
|
|
142
|
-
listener
|
|
120
|
+
listener(...emitter.args);
|
|
143
121
|
}, 1);
|
|
144
122
|
};
|
|
145
123
|
|
|
146
|
-
this.
|
|
147
|
-
this.
|
|
148
|
-
this.
|
|
149
|
-
this.
|
|
124
|
+
this._eventListeners = this._eventListeners || {};
|
|
125
|
+
this._eventListeners[eventName] = this._eventListeners[eventName] || {};
|
|
126
|
+
this._eventListeners[eventName][id] = this._eventListeners[eventName][id] || [];
|
|
127
|
+
this._eventListeners[eventName][id].push(listener);
|
|
150
128
|
|
|
151
129
|
// Check for any static emitters, and fire the event if any exist
|
|
152
|
-
if (!this.
|
|
130
|
+
if (!this._eventStaticEmitters || !this._eventStaticEmitters[eventName] || !this._eventStaticEmitters[eventName].length) return this;
|
|
153
131
|
|
|
154
132
|
// Emit events for each emitter
|
|
155
|
-
this.
|
|
133
|
+
for (let i = 0; i < this._eventStaticEmitters[eventName].length; i++) {
|
|
134
|
+
const emitter = this._eventStaticEmitters[eventName][i];
|
|
135
|
+
|
|
156
136
|
if (id === "*" || emitter.id === id) {
|
|
157
137
|
// Call the listener out of process so that any code that expects a listener
|
|
158
138
|
// to be called at some point in the future rather than immediately on registration
|
|
159
139
|
// will not fail
|
|
160
|
-
|
|
140
|
+
generateTimeout(emitter);
|
|
161
141
|
}
|
|
162
|
-
}
|
|
142
|
+
}
|
|
163
143
|
|
|
164
144
|
return this;
|
|
165
145
|
}
|
|
@@ -167,213 +147,248 @@ export class Emitter {
|
|
|
167
147
|
/**
|
|
168
148
|
* Attach an event listener to the passed event only if the passed
|
|
169
149
|
* id matches the document id for the event being fired.
|
|
170
|
-
* @
|
|
171
|
-
* @
|
|
172
|
-
* @param {String} event The name of the event to listen for.
|
|
173
|
-
* @param {*} id The document id to match against.
|
|
150
|
+
* @param {String} eventName The name of the event to listen for.
|
|
151
|
+
* @param {*} id The id to match against.
|
|
174
152
|
* @param {Function} listener The method to call when the event is fired.
|
|
175
153
|
* @returns {Emitter} The emitter instance.
|
|
176
154
|
*/
|
|
177
|
-
_once (
|
|
155
|
+
_once (eventName: string, id: string, listener: EventListenerCallback) {
|
|
178
156
|
let fired = false;
|
|
179
157
|
|
|
180
|
-
const internalCallback = (...
|
|
158
|
+
const internalCallback = (...args: any[]) => {
|
|
181
159
|
if (fired) return;
|
|
182
160
|
|
|
183
161
|
fired = true;
|
|
184
|
-
this.off(
|
|
185
|
-
listener(...
|
|
162
|
+
this.off(eventName, id, internalCallback);
|
|
163
|
+
listener(...args);
|
|
186
164
|
};
|
|
187
165
|
|
|
188
|
-
return this.on(
|
|
166
|
+
return this.on(eventName, id, internalCallback);
|
|
189
167
|
}
|
|
190
168
|
|
|
191
169
|
/**
|
|
192
170
|
* Cancels an event listener based on an event name, id and listener function.
|
|
193
|
-
* @
|
|
194
|
-
* @method off
|
|
195
|
-
* @param {String} event The event to cancel listener for.
|
|
171
|
+
* @param {String} eventName The event to cancel listener for.
|
|
196
172
|
* @param {String} id The ID of the event to cancel listening for.
|
|
197
173
|
* @param {Function} listener The event listener function used in the on()
|
|
198
174
|
* or once() call to cancel.
|
|
199
175
|
* @returns {Emitter} The emitter instance.
|
|
200
176
|
*/
|
|
201
|
-
_off (
|
|
202
|
-
|
|
177
|
+
_off (eventName: string, id: string, listener?: EventListenerCallback): this {
|
|
178
|
+
// If the event name doesn't have any listeners, exit early
|
|
179
|
+
if (!this._eventListeners || !this._eventListeners[eventName] || !this._eventListeners[eventName][id]) return this;
|
|
180
|
+
|
|
181
|
+
// If we are emitting events at the moment, don't remove this listener
|
|
182
|
+
// until the process has completed, so we queue for removal instead
|
|
183
|
+
if (this._eventsEmitting) {
|
|
203
184
|
this._eventRemovalQueue = this._eventRemovalQueue || [];
|
|
204
185
|
this._eventRemovalQueue.push(() => {
|
|
205
|
-
this.off(
|
|
186
|
+
this.off(eventName, id, listener);
|
|
206
187
|
});
|
|
207
188
|
|
|
208
189
|
return this;
|
|
209
190
|
}
|
|
210
191
|
|
|
211
|
-
if
|
|
212
|
-
|
|
213
|
-
if (
|
|
192
|
+
// Check if we have no specific listener... in this case
|
|
193
|
+
// we want to remove all listeners for an id
|
|
194
|
+
if (!listener) {
|
|
214
195
|
if (id === "*") {
|
|
215
|
-
delete
|
|
196
|
+
// The id is "all" and no listener was provided so delete all
|
|
197
|
+
// event listeners for this event name
|
|
198
|
+
delete this._eventListeners[eventName];
|
|
216
199
|
return this;
|
|
217
200
|
}
|
|
218
201
|
|
|
219
|
-
// No listener provided, delete all listeners
|
|
220
|
-
delete this.
|
|
202
|
+
// No listener provided, delete all listeners for this id
|
|
203
|
+
delete this._eventListeners[eventName][id];
|
|
221
204
|
return this;
|
|
222
205
|
}
|
|
223
206
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const arr = this._listeners[event][id] || [];
|
|
207
|
+
const arr = this._eventListeners[eventName][id] || [];
|
|
227
208
|
const index = arr.indexOf(listener);
|
|
228
209
|
|
|
229
210
|
if (index > -1) {
|
|
230
211
|
arr.splice(index, 1);
|
|
231
212
|
}
|
|
213
|
+
|
|
214
|
+
return this;
|
|
232
215
|
}
|
|
233
216
|
|
|
234
217
|
/**
|
|
235
218
|
* Attach an event listener to the passed event only if the passed
|
|
236
219
|
* id matches the document id for the event being fired.
|
|
237
|
-
* @
|
|
238
|
-
* @
|
|
239
|
-
* @param {String} event The name of the event to listen for.
|
|
240
|
-
* @param {*} id The document id to match against.
|
|
220
|
+
* @param {String} eventName The name of the event to listen for.
|
|
221
|
+
* @param {*} id The id to match against.
|
|
241
222
|
* @param {Function} listener The method to call when the event is fired.
|
|
242
223
|
* @returns {Emitter} The emitter instance.
|
|
243
224
|
*/
|
|
244
|
-
on (
|
|
245
|
-
on (
|
|
246
|
-
on (
|
|
225
|
+
on (eventName: string, id: string, listener: EventListenerCallback): this;
|
|
226
|
+
on (eventName: string, listener: EventListenerCallback): this;
|
|
227
|
+
on (eventName: string, ...rest: any[]): this {
|
|
247
228
|
const restTypes = rest.map((arg) => typeof arg);
|
|
248
229
|
|
|
249
230
|
if (restTypes[0] === "function") {
|
|
250
|
-
return this._on
|
|
231
|
+
return this._on(eventName, "*", rest[0]);
|
|
251
232
|
}
|
|
252
233
|
|
|
253
|
-
return this._on
|
|
234
|
+
return this._on(eventName, rest[0], rest[1]);
|
|
254
235
|
}
|
|
255
236
|
|
|
256
237
|
/**
|
|
257
238
|
* Attach an event listener to the passed event only if the passed
|
|
258
239
|
* id matches the document id for the event being fired.
|
|
259
|
-
* @
|
|
260
|
-
* @
|
|
261
|
-
* @param
|
|
262
|
-
* @param {*} id The document id to match against.
|
|
263
|
-
* @param {Function} listener The method to call when the event is fired.
|
|
240
|
+
* @param {String} eventName The name of the event to listen for.
|
|
241
|
+
* @param id The id to match against.
|
|
242
|
+
* @param listener
|
|
264
243
|
* @returns {Emitter} The emitter instance.
|
|
265
244
|
*/
|
|
266
|
-
once (
|
|
267
|
-
once (
|
|
268
|
-
once (
|
|
245
|
+
once (eventName: string, id: string, listener: EventListenerCallback): this;
|
|
246
|
+
once (eventName: string, listener: EventListenerCallback): this;
|
|
247
|
+
once (eventName: string, ...rest: any[]): this {
|
|
269
248
|
const restTypes = rest.map((arg) => typeof arg);
|
|
270
249
|
|
|
271
250
|
if (restTypes[0] === "function") {
|
|
272
|
-
return this._once
|
|
251
|
+
return this._once(eventName, "*", rest[0]);
|
|
273
252
|
}
|
|
274
253
|
|
|
275
|
-
return this._once
|
|
254
|
+
return this._once(eventName, rest[0], rest[1]);
|
|
276
255
|
}
|
|
277
256
|
|
|
278
257
|
/**
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
258
|
+
* Overwrites any previous event listeners so that if the event fires, only
|
|
259
|
+
* the listener you pass will be called. If you pass an id along with the
|
|
260
|
+
* listener, only listeners for the id will be overwritten. This is similar
|
|
261
|
+
* to calling `.off(eventName)` then `on(eventName, listener)` since
|
|
262
|
+
* `off(eventName)` will cancel any previous event listeners for the passed
|
|
263
|
+
* event name.
|
|
264
|
+
* @param {String} eventName The name of the event to listen for.
|
|
265
|
+
* @param {*} id The id to match against.
|
|
285
266
|
* @param {Function} listener The method to call when the event is fired.
|
|
286
267
|
* @returns {Emitter} The emitter instance.
|
|
287
268
|
*/
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
269
|
+
overwrite (eventName: string, id: string, listener: EventListenerCallback): this;
|
|
270
|
+
overwrite (eventName: string, listener: EventListenerCallback): this;
|
|
271
|
+
overwrite (eventName: string, ...rest: any[]) {
|
|
291
272
|
const restTypes = rest.map((arg) => typeof arg);
|
|
292
273
|
|
|
293
274
|
if (restTypes[0] === "function") {
|
|
294
|
-
this.off(
|
|
295
|
-
return this._on
|
|
275
|
+
this.off(eventName);
|
|
276
|
+
return this._on(eventName, "*", rest[0]);
|
|
296
277
|
}
|
|
297
278
|
|
|
298
|
-
this.off(
|
|
299
|
-
return this._on
|
|
279
|
+
this.off(eventName, rest[0]);
|
|
280
|
+
return this._on(eventName, rest[0], rest[1]);
|
|
300
281
|
}
|
|
301
282
|
|
|
302
283
|
/**
|
|
303
284
|
* Cancels an event listener based on an event name, id and listener function.
|
|
304
|
-
* @
|
|
305
|
-
* @
|
|
306
|
-
* @param
|
|
307
|
-
* @param id The ID of the event to cancel listening for.
|
|
308
|
-
* @param listener The event listener function used in the on()
|
|
285
|
+
* @param {String} eventName The event to cancel listener for.
|
|
286
|
+
* @param {String} id The ID of the event to cancel listening for.
|
|
287
|
+
* @param {Function} listener The event listener function used in the on()
|
|
309
288
|
* or once() call to cancel.
|
|
310
289
|
* @returns {Emitter} The emitter instance.
|
|
311
290
|
*/
|
|
312
|
-
off (
|
|
313
|
-
off (
|
|
314
|
-
off (
|
|
315
|
-
off (
|
|
291
|
+
off (eventName: string, id: string, listener?: EventListenerCallback): this;
|
|
292
|
+
off (eventName: string, listener?: EventListenerCallback): this;
|
|
293
|
+
off (eventName: string): this;
|
|
294
|
+
off (eventName: string, ...rest: any[]) {
|
|
316
295
|
if (rest.length === 0) {
|
|
317
|
-
// Only event was provided
|
|
318
|
-
|
|
296
|
+
// Only event was provided, use * as the id to mean "any without"
|
|
297
|
+
// a specific id
|
|
298
|
+
return this._off(eventName, "*");
|
|
319
299
|
}
|
|
320
300
|
|
|
321
301
|
const restTypes = rest.map((arg) => typeof arg);
|
|
322
302
|
|
|
323
303
|
if (restTypes[0] === "function") {
|
|
324
|
-
|
|
304
|
+
// The first arg after the event name was a function (listener)
|
|
305
|
+
// so remove listening for events for this specific listener
|
|
306
|
+
return this._off(eventName, "*", rest[0]);
|
|
325
307
|
}
|
|
326
308
|
|
|
327
|
-
|
|
309
|
+
// Both id and listener were provided, remove for the specific id
|
|
310
|
+
return this._off(eventName, rest[0], rest[1]);
|
|
328
311
|
}
|
|
329
312
|
|
|
330
313
|
/**
|
|
331
|
-
*
|
|
332
|
-
* @param {
|
|
333
|
-
* @param {
|
|
334
|
-
*
|
|
335
|
-
*
|
|
314
|
+
* Emit an event by name.
|
|
315
|
+
* @param {Object} eventName The name of the event to emit.
|
|
316
|
+
* @param {...any} data The arguments to send to any listening methods.
|
|
317
|
+
* If you are sending multiple arguments, separate them with a comma so
|
|
318
|
+
* that they are received by the function as separate arguments.
|
|
319
|
+
* @return {number}
|
|
320
|
+
* @example #Emit an Event
|
|
321
|
+
* // Emit the event named "hello"
|
|
322
|
+
* myEntity.emit('hello');
|
|
323
|
+
* @example #Emit an Event With Data Object
|
|
324
|
+
* // Emit the event named "hello"
|
|
325
|
+
* myEntity.emit('hello', {moo: true});
|
|
326
|
+
* @example #Emit an Event With Multiple Data Values
|
|
327
|
+
* // Emit the event named "hello"
|
|
328
|
+
* myEntity.emit('hello', {moo: true}, 'someString');
|
|
329
|
+
* @example #Listen for Event Data
|
|
330
|
+
* // Set a listener to listen for the data (multiple values emitted
|
|
331
|
+
* // from an event are passed as function arguments)
|
|
332
|
+
* myEntity.on('hello', function (arg1, arg2) {
|
|
333
|
+
* console.log(arg1, arg2);
|
|
334
|
+
* }
|
|
335
|
+
*
|
|
336
|
+
* // Emit the event named "hello"
|
|
337
|
+
* myEntity.emit('hello', 'data1', 'data2');
|
|
338
|
+
*
|
|
339
|
+
* // The console output is:
|
|
340
|
+
* // data1, data2
|
|
336
341
|
*/
|
|
337
|
-
emit (
|
|
342
|
+
async emit (eventName: string, ...data: any[]): Promise<EventReturnFlag> {
|
|
343
|
+
if (!this._eventListeners) {
|
|
344
|
+
return EventReturnFlag.none;
|
|
345
|
+
}
|
|
346
|
+
|
|
338
347
|
const id = "*";
|
|
339
|
-
this._listeners = this._listeners || {};
|
|
340
|
-
this._emitting = true;
|
|
341
348
|
|
|
342
|
-
|
|
349
|
+
let returnFlag: EventReturnFlag = EventReturnFlag.none;
|
|
350
|
+
this._eventsEmitting = true;
|
|
351
|
+
|
|
352
|
+
if (this._eventListeners[eventName] && this._eventListeners[eventName][id]) {
|
|
343
353
|
// Handle global emit
|
|
344
|
-
const arr = this.
|
|
345
|
-
const arrCount = arr.length;
|
|
354
|
+
const arr = this._eventListeners[eventName][id];
|
|
346
355
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
356
|
+
const promiseArr = arr.map((tmpFunc) => {
|
|
357
|
+
if (typeof tmpFunc !== "function") return;
|
|
358
|
+
return tmpFunc(...data);
|
|
359
|
+
});
|
|
350
360
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
361
|
+
const result = (await Promise.all(promiseArr)).find((tmpResult) => tmpResult !== EventReturnFlag.none);
|
|
362
|
+
|
|
363
|
+
if (result) {
|
|
364
|
+
returnFlag = EventReturnFlag.cancel;
|
|
354
365
|
}
|
|
355
366
|
}
|
|
356
367
|
|
|
357
|
-
this.
|
|
368
|
+
this._eventsEmitting = false;
|
|
358
369
|
this._processRemovalQueue();
|
|
359
370
|
|
|
360
|
-
return
|
|
371
|
+
return returnFlag;
|
|
361
372
|
}
|
|
362
373
|
|
|
363
|
-
emitId (
|
|
364
|
-
|
|
365
|
-
|
|
374
|
+
emitId (eventName: string, id: string, ...data: any[]): EventReturnFlag {
|
|
375
|
+
if (!this._eventListeners) {
|
|
376
|
+
return EventReturnFlag.none;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
this._eventListeners = this._eventListeners || {};
|
|
380
|
+
this._eventsEmitting = true;
|
|
366
381
|
|
|
367
|
-
if (!this.
|
|
368
|
-
this.
|
|
382
|
+
if (!this._eventListeners[eventName]) {
|
|
383
|
+
this._eventsEmitting = false;
|
|
369
384
|
this._processRemovalQueue();
|
|
370
385
|
|
|
371
|
-
return
|
|
386
|
+
return EventReturnFlag.none;
|
|
372
387
|
}
|
|
373
388
|
|
|
374
389
|
// Handle id emit
|
|
375
|
-
if (this.
|
|
376
|
-
const arr = this.
|
|
390
|
+
if (this._eventListeners[eventName][id]) {
|
|
391
|
+
const arr = this._eventListeners[eventName][id];
|
|
377
392
|
const arrCount = arr.length;
|
|
378
393
|
|
|
379
394
|
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
@@ -387,8 +402,8 @@ export class Emitter {
|
|
|
387
402
|
}
|
|
388
403
|
|
|
389
404
|
// Handle global emit
|
|
390
|
-
if (this.
|
|
391
|
-
const arr = this.
|
|
405
|
+
if (this._eventListeners[eventName]["*"]) {
|
|
406
|
+
const arr = this._eventListeners[eventName]["*"];
|
|
392
407
|
const arrCount = arr.length;
|
|
393
408
|
|
|
394
409
|
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
@@ -401,86 +416,144 @@ export class Emitter {
|
|
|
401
416
|
}
|
|
402
417
|
}
|
|
403
418
|
|
|
404
|
-
this.
|
|
419
|
+
this._eventsEmitting = false;
|
|
405
420
|
this._processRemovalQueue();
|
|
406
421
|
|
|
407
|
-
return
|
|
422
|
+
return EventReturnFlag.none;
|
|
408
423
|
}
|
|
409
424
|
|
|
410
425
|
/**
|
|
411
|
-
* Creates a
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
* @param {
|
|
426
|
+
* Creates a persistent emitter record that will fire a listener if
|
|
427
|
+
* one is added for this event after the emitStatic() call has been
|
|
428
|
+
* made.
|
|
429
|
+
* @param {String} eventName The name of the event to emit.
|
|
430
|
+
* @param {...any} data Optional arguments to emit with the event.
|
|
415
431
|
* @returns {Emitter} The emitter instance.
|
|
432
|
+
* @private
|
|
416
433
|
*/
|
|
417
|
-
emitStatic (
|
|
418
|
-
|
|
419
|
-
this.
|
|
420
|
-
this.
|
|
434
|
+
emitStatic (eventName: string, ...data: any[]) {
|
|
435
|
+
const id = "*";
|
|
436
|
+
this._eventListeners = this._eventListeners || {};
|
|
437
|
+
this._eventsEmitting = true;
|
|
438
|
+
|
|
439
|
+
if (this._eventListeners[eventName] && this._eventListeners[eventName][id]) {
|
|
440
|
+
// Handle global emit
|
|
441
|
+
const arr = this._eventListeners[eventName][id];
|
|
442
|
+
const arrCount = arr.length;
|
|
443
|
+
|
|
444
|
+
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
445
|
+
// Check we have a function to execute
|
|
446
|
+
const tmpFunc = arr[arrIndex];
|
|
447
|
+
|
|
448
|
+
if (typeof tmpFunc === "function") {
|
|
449
|
+
tmpFunc.call(this, ...data);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
this._eventsEmitting = false;
|
|
455
|
+
|
|
456
|
+
this._eventStaticEmitters = this._eventStaticEmitters || {};
|
|
457
|
+
this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
|
|
458
|
+
this._eventStaticEmitters[eventName].push({
|
|
421
459
|
"id": "*",
|
|
422
460
|
"args": data
|
|
423
461
|
});
|
|
424
462
|
|
|
425
|
-
this.emit(event, ...data);
|
|
426
|
-
|
|
427
463
|
this._processRemovalQueue();
|
|
428
464
|
|
|
429
465
|
return this;
|
|
430
466
|
}
|
|
431
467
|
|
|
432
468
|
/**
|
|
433
|
-
* Creates a
|
|
434
|
-
*
|
|
435
|
-
*
|
|
469
|
+
* Creates a persistent emitter record that will fire a listener if
|
|
470
|
+
* one is added for this event after the emitStatic() call has been
|
|
471
|
+
* made.
|
|
472
|
+
* @param {String} eventName The name of the event to emit.
|
|
436
473
|
* @param {String} id The id of the event to emit.
|
|
437
|
-
* @param {
|
|
474
|
+
* @param {...any} data Optional arguments to emit with the event.
|
|
438
475
|
* @returns {Emitter} The emitter instance.
|
|
476
|
+
* @private
|
|
439
477
|
*/
|
|
440
|
-
emitStaticId (
|
|
441
|
-
if (!id) throw new Error("Missing id from
|
|
478
|
+
emitStaticId (eventName: string, id: string, ...data: any[]) {
|
|
479
|
+
if (!id) throw new Error("Missing id from emitId call!");
|
|
480
|
+
|
|
481
|
+
this._eventListeners = this._eventListeners || {};
|
|
482
|
+
this._eventsEmitting = true;
|
|
483
|
+
|
|
484
|
+
if (this._eventListeners[eventName]) {
|
|
485
|
+
// Handle id emit
|
|
486
|
+
if (this._eventListeners[eventName][id]) {
|
|
487
|
+
const arr = this._eventListeners[eventName][id];
|
|
488
|
+
const arrCount = arr.length;
|
|
442
489
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
490
|
+
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
491
|
+
// Check we have a function to execute
|
|
492
|
+
const tmpFunc = arr[arrIndex];
|
|
493
|
+
|
|
494
|
+
if (typeof tmpFunc === "function") {
|
|
495
|
+
tmpFunc.call(this, ...data);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Handle global emit
|
|
501
|
+
if (this._eventListeners[eventName]["*"]) {
|
|
502
|
+
const arr = this._eventListeners[eventName]["*"];
|
|
503
|
+
const arrCount = arr.length;
|
|
504
|
+
|
|
505
|
+
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
506
|
+
// Check we have a function to execute
|
|
507
|
+
const tmpFunc = arr[arrIndex];
|
|
508
|
+
|
|
509
|
+
if (typeof tmpFunc === "function") {
|
|
510
|
+
tmpFunc.call(this, ...data);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
this._eventsEmitting = false;
|
|
517
|
+
|
|
518
|
+
this._eventStaticEmitters = this._eventStaticEmitters || {};
|
|
519
|
+
this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
|
|
520
|
+
this._eventStaticEmitters[eventName].push({
|
|
446
521
|
id,
|
|
447
522
|
"args": data
|
|
448
523
|
});
|
|
449
524
|
|
|
450
|
-
this.
|
|
525
|
+
this._processRemovalQueue();
|
|
451
526
|
|
|
452
527
|
return this;
|
|
453
528
|
}
|
|
454
529
|
|
|
455
530
|
/**
|
|
456
531
|
* Handles removing emitters, is an internal method not called directly.
|
|
457
|
-
* @param {String}
|
|
532
|
+
* @param {String} eventName The event to remove static emitter for.
|
|
458
533
|
* @returns {Emitter} The emitter instance.
|
|
459
534
|
* @private
|
|
460
535
|
*/
|
|
461
|
-
cancelStatic (
|
|
462
|
-
this.
|
|
463
|
-
this.
|
|
536
|
+
cancelStatic (eventName: string) {
|
|
537
|
+
this._eventStaticEmitters = this._eventStaticEmitters || {};
|
|
538
|
+
this._eventStaticEmitters[eventName] = [];
|
|
464
539
|
|
|
465
540
|
return this;
|
|
466
541
|
}
|
|
467
542
|
|
|
468
543
|
/**
|
|
469
544
|
* Checks if an event has any event listeners or not.
|
|
470
|
-
* @
|
|
471
|
-
* @method willEmit
|
|
472
|
-
* @param {String} event The name of the event to check for.
|
|
545
|
+
* @param {String} eventName The name of the event to check for.
|
|
473
546
|
* @returns {boolean} True if one or more event listeners are registered for
|
|
474
547
|
* the event. False if none are found.
|
|
475
548
|
*/
|
|
476
|
-
willEmit (
|
|
549
|
+
willEmit (eventName: string) {
|
|
477
550
|
const id = "*";
|
|
478
551
|
|
|
479
|
-
if (!this.
|
|
552
|
+
if (!this._eventListeners || !this._eventListeners[eventName]) {
|
|
480
553
|
return false;
|
|
481
554
|
}
|
|
482
555
|
|
|
483
|
-
const arr = this.
|
|
556
|
+
const arr = this._eventListeners[eventName][id];
|
|
484
557
|
const arrCount = arr.length;
|
|
485
558
|
|
|
486
559
|
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
@@ -497,21 +570,19 @@ export class Emitter {
|
|
|
497
570
|
|
|
498
571
|
/**
|
|
499
572
|
* Checks if an event has any event listeners or not based on the passed id.
|
|
500
|
-
* @
|
|
501
|
-
* @method willEmitId
|
|
502
|
-
* @param {String} event The name of the event to check for.
|
|
573
|
+
* @param {String} eventName The name of the event to check for.
|
|
503
574
|
* @param {String} id The event ID to check for.
|
|
504
575
|
* @returns {boolean} True if one or more event listeners are registered for
|
|
505
576
|
* the event. False if none are found.
|
|
506
577
|
*/
|
|
507
|
-
willEmitId (
|
|
508
|
-
if (!this.
|
|
578
|
+
willEmitId (eventName: string, id: string) {
|
|
579
|
+
if (!this._eventListeners || !this._eventListeners[eventName]) {
|
|
509
580
|
return false;
|
|
510
581
|
}
|
|
511
582
|
|
|
512
583
|
// Handle id emit
|
|
513
|
-
if (this.
|
|
514
|
-
const arr = this.
|
|
584
|
+
if (this._eventListeners[eventName][id]) {
|
|
585
|
+
const arr = this._eventListeners[eventName][id];
|
|
515
586
|
const arrCount = arr.length;
|
|
516
587
|
|
|
517
588
|
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
@@ -525,8 +596,8 @@ export class Emitter {
|
|
|
525
596
|
}
|
|
526
597
|
|
|
527
598
|
// Handle global emit
|
|
528
|
-
if (this.
|
|
529
|
-
const arr = this.
|
|
599
|
+
if (this._eventListeners[eventName]["*"]) {
|
|
600
|
+
const arr = this._eventListeners[eventName]["*"];
|
|
530
601
|
const arrCount = arr.length;
|
|
531
602
|
|
|
532
603
|
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
@@ -546,32 +617,29 @@ export class Emitter {
|
|
|
546
617
|
* Queues an event to be fired. This has automatic de-bouncing so that any
|
|
547
618
|
* events of the same type that occur within 100 milliseconds of a previous
|
|
548
619
|
* one will all be wrapped into a single emit rather than emitting tons of
|
|
549
|
-
* events for
|
|
550
|
-
* will be emitted.
|
|
551
|
-
* @memberOf Emitter
|
|
552
|
-
* @method deferEmit
|
|
620
|
+
* events for lots of chained inserts etc. Only the data from the last
|
|
621
|
+
* de-bounced event will be emitted.
|
|
553
622
|
* @param {String} eventName The name of the event to emit.
|
|
554
|
-
* @param {
|
|
623
|
+
* @param {...any} data Optional arguments to emit with the event.
|
|
555
624
|
* @returns {Emitter} The emitter instance.
|
|
556
625
|
*/
|
|
557
|
-
deferEmit (eventName: string
|
|
558
|
-
if (this.
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
}
|
|
626
|
+
deferEmit (eventName: string, ...data: any[]) {
|
|
627
|
+
if (!this._eventsAllowDefer) {
|
|
628
|
+
// Check for an existing timeout
|
|
629
|
+
this._eventsDeferTimeouts = this._eventsDeferTimeouts || {};
|
|
562
630
|
|
|
563
|
-
|
|
564
|
-
|
|
631
|
+
if (this._eventsDeferTimeouts[eventName]) {
|
|
632
|
+
clearTimeout(this._eventsDeferTimeouts[eventName]);
|
|
633
|
+
}
|
|
565
634
|
|
|
566
|
-
|
|
567
|
-
|
|
635
|
+
// Set a timeout
|
|
636
|
+
this._eventsDeferTimeouts[eventName] = setTimeout(() => {
|
|
637
|
+
this.emit.call(this, eventName, ...data);
|
|
638
|
+
}, 1) as unknown as number;
|
|
639
|
+
} else {
|
|
640
|
+
this.emit.call(this, eventName, ...data);
|
|
568
641
|
}
|
|
569
642
|
|
|
570
|
-
// Set a timeout
|
|
571
|
-
this._deferTimeout[eventName] = setTimeout(() => {
|
|
572
|
-
this.emit(eventName, ...data);
|
|
573
|
-
}, 100);
|
|
574
|
-
|
|
575
643
|
return this;
|
|
576
644
|
}
|
|
577
645
|
|
|
@@ -583,7 +651,6 @@ export class Emitter {
|
|
|
583
651
|
* the emitter is running through them. This method is called after the
|
|
584
652
|
* event emitter is finished processing.
|
|
585
653
|
* @private
|
|
586
|
-
* @returns {undefined}
|
|
587
654
|
*/
|
|
588
655
|
_processRemovalQueue () {
|
|
589
656
|
if (!this._eventRemovalQueue || !this._eventRemovalQueue.length) {
|
|
@@ -600,26 +667,10 @@ export class Emitter {
|
|
|
600
667
|
}
|
|
601
668
|
}
|
|
602
669
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
* If none is provided a new object will be created. This allows you to use
|
|
608
|
-
* new Emitter() to generate an event emitter that is not tied to any other
|
|
609
|
-
* object or class.
|
|
610
|
-
* @param prototypeMode Defaults to true. Set to true to add emitter
|
|
611
|
-
* methods to the the passed object"s prototype property e.g. obj.prototype.on
|
|
612
|
-
* = emitter.on. Set to false to add emitter methods the object directly e.g.
|
|
613
|
-
* obj.on = emitter.on.
|
|
614
|
-
* @returns {Object} The newly augmented object.
|
|
615
|
-
*/
|
|
616
|
-
type MakeEmitter = {
|
|
617
|
-
(obj: Record<string, unknown>|boolean|undefined, prototypeMode: boolean): any,
|
|
618
|
-
(obj: boolean): any,
|
|
619
|
-
(obj: undefined): any
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
export const makeEmitter: MakeEmitter = (obj: Record<string, unknown>|boolean|undefined, prototypeMode = false) => {
|
|
670
|
+
export function makeEmitter(obj: new (...args: any[]) => any, prototypeMode: boolean): Emitter;
|
|
671
|
+
export function makeEmitter(obj: boolean): Emitter;
|
|
672
|
+
export function makeEmitter(obj: Record<string, unknown>, prototypeMode: boolean): Emitter;
|
|
673
|
+
export function makeEmitter (obj: any, prototypeMode?: any) {
|
|
623
674
|
let operateOnObject;
|
|
624
675
|
|
|
625
676
|
if (obj === undefined && prototypeMode === undefined) {
|
|
@@ -633,27 +684,26 @@ export const makeEmitter: MakeEmitter = (obj: Record<string, unknown>|boolean|un
|
|
|
633
684
|
}
|
|
634
685
|
|
|
635
686
|
if (prototypeMode === undefined) {
|
|
636
|
-
prototypeMode =
|
|
687
|
+
prototypeMode = true;
|
|
637
688
|
}
|
|
638
689
|
|
|
639
690
|
if (typeof obj !== "object" && typeof obj !== "function") {
|
|
640
|
-
throw new Error("Cannot operate on
|
|
691
|
+
throw new Error("Cannot operate on a non-object / non-function passed as first argument!");
|
|
641
692
|
}
|
|
642
693
|
|
|
643
694
|
if (prototypeMode) {
|
|
644
695
|
if (obj.prototype === undefined) {
|
|
645
|
-
throw new Error("Cannot modify prototype of passed object, it has no prototype property!");
|
|
696
|
+
throw new Error("Cannot modify prototype of passed object, it has no prototype property! Was it instantiated with the new operator correctly?");
|
|
646
697
|
}
|
|
647
698
|
|
|
648
|
-
operateOnObject = obj.prototype
|
|
699
|
+
operateOnObject = obj.prototype;
|
|
649
700
|
} else {
|
|
650
701
|
operateOnObject = obj;
|
|
651
702
|
}
|
|
652
703
|
|
|
653
|
-
// Convert the object to have eventing capability
|
|
704
|
+
// Convert the object prototype to have eventing capability
|
|
654
705
|
operateOnObject.on = Emitter.prototype.on;
|
|
655
706
|
operateOnObject.off = Emitter.prototype.off;
|
|
656
|
-
operateOnObject.one = Emitter.prototype.one;
|
|
657
707
|
operateOnObject.once = Emitter.prototype.once;
|
|
658
708
|
operateOnObject.emit = Emitter.prototype.emit;
|
|
659
709
|
operateOnObject.emitId = Emitter.prototype.emitId;
|
|
@@ -664,9 +714,6 @@ export const makeEmitter: MakeEmitter = (obj: Record<string, unknown>|boolean|un
|
|
|
664
714
|
operateOnObject.willEmit = Emitter.prototype.willEmit;
|
|
665
715
|
operateOnObject.willEmitId = Emitter.prototype.willEmitId;
|
|
666
716
|
operateOnObject._processRemovalQueue = Emitter.prototype._processRemovalQueue;
|
|
667
|
-
operateOnObject._on = Emitter.prototype._on;
|
|
668
|
-
operateOnObject._off = Emitter.prototype._off;
|
|
669
|
-
operateOnObject._once = Emitter.prototype._once;
|
|
670
717
|
|
|
671
718
|
return obj;
|
|
672
|
-
}
|
|
719
|
+
}
|