@irrelon/emitter 5.0.6 → 6.0.1
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 +2 -1
- package/.prettierignore +2 -1
- package/.prettierrc.yml +18 -1
- package/dist/cjs/src/Emitter.d.ts +71 -20
- package/dist/cjs/src/Emitter.js +128 -78
- package/dist/cjs/tests/Emitter.test.js +125 -52
- package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/{mjs → esm}/src/Emitter.d.ts +71 -20
- package/dist/{mjs → esm}/src/Emitter.js +128 -67
- package/dist/{mjs → esm}/tests/Emitter.test.js +123 -50
- package/dist/esm/tsconfig-esm.tsbuildinfo +1 -0
- package/fixup.sh +1 -1
- package/package.json +8 -7
- package/readme.md +101 -20
- package/src/Emitter.ts +287 -114
- package/tests/Emitter.test.ts +249 -82
- package/tsconfig-cjs.json +1 -1
- package/tsconfig-esm.json +8 -0
- package/tsconfig.json +33 -5
- package/fixPaths.cjs +0 -183
- package/tsconfig-base.json +0 -36
- /package/dist/{mjs → esm}/package.json +0 -0
- /package/dist/{mjs → esm}/tests/Emitter.test.d.ts +0 -0
- /package/dist/{mjs → esm}/tsconfig.tsbuildinfo +0 -0
package/src/Emitter.ts
CHANGED
|
@@ -25,12 +25,24 @@
|
|
|
25
25
|
Source: https://github.com/irrelon/emitter
|
|
26
26
|
|
|
27
27
|
Changelog:
|
|
28
|
+
Version 6.0.0: Updated to allow event listeners to return data to
|
|
29
|
+
the caller of the emit() function, e.g.
|
|
30
|
+
`const results = emitter.emit("myEventName");`
|
|
31
|
+
|
|
32
|
+
The results are an array of all return values from any listener
|
|
33
|
+
functions that were called by the event "myEventName". This is
|
|
34
|
+
useful if you want event listeners to act as data providers for
|
|
35
|
+
particular events.
|
|
36
|
+
|
|
37
|
+
Listeners that return `ListenerReturnFlag.cancel` will cancel
|
|
38
|
+
the event call to any further listeners for that one event
|
|
39
|
+
emit.
|
|
28
40
|
Version 5.0.3 and 5.0.4: Updated to allow specifying an events type
|
|
29
41
|
to the Emitter to allow complete type safety when registering
|
|
30
42
|
listeners and emitting events.
|
|
31
43
|
|
|
32
44
|
Updated the build and package to split between delivery of CJS
|
|
33
|
-
and
|
|
45
|
+
and ESM module types so that this package can be eiter imported
|
|
34
46
|
or required without having to jump through any hoops.
|
|
35
47
|
Version 5.0.2:
|
|
36
48
|
Removed some unnecessary code, updated to be in step with version
|
|
@@ -94,34 +106,40 @@
|
|
|
94
106
|
export type AnyFunction<ReturnType = any> = (...args: any[]) => ReturnType;
|
|
95
107
|
export type AnyConstructor = new (...args: any[]) => any;
|
|
96
108
|
|
|
97
|
-
export enum
|
|
98
|
-
none,
|
|
99
|
-
cancel
|
|
109
|
+
export enum ListenerReturnFlag {
|
|
110
|
+
none = "!+_NONE",
|
|
111
|
+
cancel = "!+_CANCEL"
|
|
100
112
|
}
|
|
101
113
|
|
|
102
|
-
export type EventListenerCallback<EventCallbackFunctionSignature extends AnyFunction = AnyFunction> = (
|
|
114
|
+
export type EventListenerCallback<EventCallbackFunctionSignature extends AnyFunction = AnyFunction> = (
|
|
115
|
+
...args: Parameters<EventCallbackFunctionSignature>
|
|
116
|
+
) => ReturnType<EventCallbackFunctionSignature>;
|
|
103
117
|
|
|
104
118
|
export interface EventStaticEmitterObject<EventCallbackFunctionSignature extends AnyFunction = AnyFunction> {
|
|
105
119
|
id: string;
|
|
106
120
|
args: Parameters<EventCallbackFunctionSignature>;
|
|
107
121
|
}
|
|
108
122
|
|
|
109
|
-
export interface
|
|
110
|
-
[key: string]: AnyFunction
|
|
123
|
+
export interface EmitterAnyEventsInterface {
|
|
124
|
+
[key: string]: AnyFunction;
|
|
111
125
|
}
|
|
112
126
|
|
|
113
|
-
export type
|
|
127
|
+
export type EmitterEventsInterface<T> = {
|
|
114
128
|
[K in keyof T]: T[K];
|
|
115
129
|
};
|
|
116
130
|
|
|
117
131
|
/**
|
|
118
132
|
* Creates a new class with the capability to emit events.
|
|
119
133
|
*/
|
|
120
|
-
export class Emitter<EventsInterface extends EmitterEventsInterface =
|
|
134
|
+
export class Emitter<EventsInterface extends EmitterEventsInterface<EventsInterface> = EmitterAnyEventsInterface> {
|
|
121
135
|
_eventsEmitting: boolean = false;
|
|
122
136
|
_eventRemovalQueue: any[] = [];
|
|
123
|
-
_eventListeners?: {
|
|
124
|
-
|
|
137
|
+
_eventListeners?: {
|
|
138
|
+
[EventName in keyof EventsInterface]?: Record<string, EventListenerCallback<EventsInterface[EventName]>[]>;
|
|
139
|
+
} = {};
|
|
140
|
+
_eventStaticEmitters: {
|
|
141
|
+
[EventName in keyof EventsInterface]?: EventStaticEmitterObject<EventsInterface[EventName]>[];
|
|
142
|
+
} = {};
|
|
125
143
|
_eventsAllowDefer: boolean = false;
|
|
126
144
|
_eventsDeferTimeouts: Record<any, number> = {};
|
|
127
145
|
|
|
@@ -133,7 +151,11 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
133
151
|
* @param listener The method to call when the event is fired.
|
|
134
152
|
* @returns The emitter instance.
|
|
135
153
|
*/
|
|
136
|
-
_on<EventName extends keyof EventsInterface>
|
|
154
|
+
_on<EventName extends keyof EventsInterface>(
|
|
155
|
+
eventName: EventName,
|
|
156
|
+
id: string,
|
|
157
|
+
listener: EventListenerCallback<EventsInterface[EventName]>
|
|
158
|
+
) {
|
|
137
159
|
const generateTimeout = (emitter: EventStaticEmitterObject<EventsInterface[EventName]>) => {
|
|
138
160
|
setTimeout(() => {
|
|
139
161
|
listener(...emitter.args);
|
|
@@ -141,12 +163,17 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
141
163
|
};
|
|
142
164
|
|
|
143
165
|
this._eventListeners = this._eventListeners || {};
|
|
144
|
-
const nonNullableEventListeners = this._eventListeners[eventName] = this._eventListeners[eventName] || {};
|
|
166
|
+
const nonNullableEventListeners = (this._eventListeners[eventName] = this._eventListeners[eventName] || {});
|
|
145
167
|
nonNullableEventListeners[id] = nonNullableEventListeners[id] || [];
|
|
146
168
|
nonNullableEventListeners[id].push(listener);
|
|
147
169
|
|
|
148
170
|
// Check for any static emitters, and fire the event if any exist
|
|
149
|
-
if (
|
|
171
|
+
if (
|
|
172
|
+
!this._eventStaticEmitters ||
|
|
173
|
+
!this._eventStaticEmitters[eventName] ||
|
|
174
|
+
!this._eventStaticEmitters[eventName]!.length
|
|
175
|
+
)
|
|
176
|
+
return this;
|
|
150
177
|
|
|
151
178
|
// Emit events for each emitter
|
|
152
179
|
for (let i = 0; i < this._eventStaticEmitters[eventName]!.length; i++) {
|
|
@@ -171,11 +198,17 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
171
198
|
* @param listener The method to call when the event is fired.
|
|
172
199
|
* @returns The emitter instance.
|
|
173
200
|
*/
|
|
174
|
-
_once<EventName extends keyof EventsInterface>
|
|
201
|
+
_once<EventName extends keyof EventsInterface>(
|
|
202
|
+
eventName: EventName,
|
|
203
|
+
id: string,
|
|
204
|
+
listener: EventListenerCallback<EventsInterface[EventName]>
|
|
205
|
+
) {
|
|
175
206
|
let fired = false;
|
|
176
207
|
let originalReturnData: ReturnType<EventsInterface[EventName]>;
|
|
177
208
|
|
|
178
|
-
const internalCallback: EventListenerCallback<EventsInterface[EventName]> = (
|
|
209
|
+
const internalCallback: EventListenerCallback<EventsInterface[EventName]> = (
|
|
210
|
+
...args: Parameters<EventsInterface[EventName]>
|
|
211
|
+
): ReturnType<EventsInterface[EventName]> => {
|
|
179
212
|
if (fired) return originalReturnData;
|
|
180
213
|
|
|
181
214
|
fired = true;
|
|
@@ -196,9 +229,14 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
196
229
|
* or once() call to cancel.
|
|
197
230
|
* @returns The emitter instance.
|
|
198
231
|
*/
|
|
199
|
-
_off<EventName extends keyof EventsInterface>
|
|
232
|
+
_off<EventName extends keyof EventsInterface>(
|
|
233
|
+
eventName: EventName,
|
|
234
|
+
id: string,
|
|
235
|
+
listener?: EventListenerCallback<EventsInterface[EventName]>
|
|
236
|
+
): this {
|
|
200
237
|
// If the event name doesn't have any listeners, exit early
|
|
201
|
-
if (!this._eventListeners || !this._eventListeners[eventName] || !this._eventListeners[eventName]![id])
|
|
238
|
+
if (!this._eventListeners || !this._eventListeners[eventName] || !this._eventListeners[eventName]![id])
|
|
239
|
+
return this;
|
|
202
240
|
|
|
203
241
|
// If we are emitting events at the moment, don't remove this listener
|
|
204
242
|
// until the process has completed, so we queue for removal instead
|
|
@@ -244,9 +282,20 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
244
282
|
* @param listener The method to call when the event is fired.
|
|
245
283
|
* @returns The emitter instance.
|
|
246
284
|
*/
|
|
247
|
-
on<EventName extends keyof EventsInterface>
|
|
248
|
-
|
|
249
|
-
|
|
285
|
+
on<EventName extends keyof EventsInterface>(
|
|
286
|
+
eventName: EventName,
|
|
287
|
+
id: string,
|
|
288
|
+
listener: EventListenerCallback<EventsInterface[EventName]>
|
|
289
|
+
): this;
|
|
290
|
+
on<EventName extends keyof EventsInterface>(
|
|
291
|
+
eventName: EventName,
|
|
292
|
+
listener: EventListenerCallback<EventsInterface[EventName]>
|
|
293
|
+
): this;
|
|
294
|
+
on<EventName extends keyof EventsInterface>(
|
|
295
|
+
eventName: EventName,
|
|
296
|
+
idOrListener: string | EventListenerCallback<EventsInterface[EventName]>,
|
|
297
|
+
listener?: EventListenerCallback<EventsInterface[EventName]>
|
|
298
|
+
): this {
|
|
250
299
|
if (typeof idOrListener === "string") {
|
|
251
300
|
return this._on(eventName, idOrListener, listener as EventListenerCallback<EventsInterface[EventName]>);
|
|
252
301
|
}
|
|
@@ -262,9 +311,16 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
262
311
|
* @param listener
|
|
263
312
|
* @returns The emitter instance.
|
|
264
313
|
*/
|
|
265
|
-
once<EventName extends keyof EventsInterface>
|
|
266
|
-
|
|
267
|
-
|
|
314
|
+
once<EventName extends keyof EventsInterface>(
|
|
315
|
+
eventName: EventName,
|
|
316
|
+
id: string,
|
|
317
|
+
listener: EventListenerCallback<EventsInterface[EventName]>
|
|
318
|
+
): this;
|
|
319
|
+
once<EventName extends keyof EventsInterface>(
|
|
320
|
+
eventName: EventName,
|
|
321
|
+
listener: EventListenerCallback<EventsInterface[EventName]>
|
|
322
|
+
): this;
|
|
323
|
+
once<EventName extends keyof EventsInterface>(eventName: EventName, ...rest: any[]): this {
|
|
268
324
|
const restTypes = rest.map((arg) => typeof arg);
|
|
269
325
|
|
|
270
326
|
if (restTypes[0] === "function") {
|
|
@@ -286,9 +342,16 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
286
342
|
* @param listener The method to call when the event is fired.
|
|
287
343
|
* @returns The emitter instance.
|
|
288
344
|
*/
|
|
289
|
-
overwrite<EventName extends keyof EventsInterface>
|
|
290
|
-
|
|
291
|
-
|
|
345
|
+
overwrite<EventName extends keyof EventsInterface>(
|
|
346
|
+
eventName: EventName,
|
|
347
|
+
id: string,
|
|
348
|
+
listener: EventListenerCallback<EventsInterface[EventName]>
|
|
349
|
+
): this;
|
|
350
|
+
overwrite<EventName extends keyof EventsInterface>(
|
|
351
|
+
eventName: EventName,
|
|
352
|
+
listener: EventListenerCallback<EventsInterface[EventName]>
|
|
353
|
+
): this;
|
|
354
|
+
overwrite<EventName extends keyof EventsInterface>(eventName: EventName, ...rest: any[]) {
|
|
292
355
|
const restTypes = rest.map((arg) => typeof arg);
|
|
293
356
|
|
|
294
357
|
if (restTypes[0] === "function") {
|
|
@@ -308,10 +371,17 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
308
371
|
* or once() call to cancel.
|
|
309
372
|
* @returns The emitter instance.
|
|
310
373
|
*/
|
|
311
|
-
off<EventName extends keyof EventsInterface>
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
374
|
+
off<EventName extends keyof EventsInterface>(
|
|
375
|
+
eventName: EventName,
|
|
376
|
+
id: string,
|
|
377
|
+
listener?: EventListenerCallback<EventsInterface[EventName]>
|
|
378
|
+
): this;
|
|
379
|
+
off<EventName extends keyof EventsInterface>(
|
|
380
|
+
eventName: EventName,
|
|
381
|
+
listener?: EventListenerCallback<EventsInterface[EventName]>
|
|
382
|
+
): this;
|
|
383
|
+
off<EventName extends keyof EventsInterface>(eventName: EventName): this;
|
|
384
|
+
off<EventName extends keyof EventsInterface>(eventName: EventName, ...rest: any[]) {
|
|
315
385
|
if (rest.length === 0) {
|
|
316
386
|
// Only event was provided, use * as the id to mean "any without"
|
|
317
387
|
// a specific id
|
|
@@ -330,116 +400,198 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
330
400
|
return this._off(eventName, rest[0], rest[1]);
|
|
331
401
|
}
|
|
332
402
|
|
|
403
|
+
_emitToSingleListener<EventName extends keyof EventsInterface>(
|
|
404
|
+
listener: EventListenerCallback<EventsInterface[EventName]>,
|
|
405
|
+
data: Parameters<EventsInterface[EventName]>
|
|
406
|
+
): ReturnType<EventsInterface[EventName]> | ListenerReturnFlag {
|
|
407
|
+
return listener(...data);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
_emitToArrayOfListeners<EventName extends keyof EventsInterface>(
|
|
411
|
+
arr: EventListenerCallback<EventsInterface[EventName]>[],
|
|
412
|
+
data: Parameters<EventsInterface[EventName]>
|
|
413
|
+
): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] {
|
|
414
|
+
const arrCount = arr.length;
|
|
415
|
+
const resultArr: (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] = [];
|
|
416
|
+
|
|
417
|
+
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
418
|
+
// Check we have a function to execute
|
|
419
|
+
const tmpFunc = arr[arrIndex];
|
|
420
|
+
|
|
421
|
+
if (typeof tmpFunc !== "function") {
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const eventListenerResponse = tmpFunc(...data);
|
|
426
|
+
resultArr.push(eventListenerResponse);
|
|
427
|
+
|
|
428
|
+
if (eventListenerResponse === ListenerReturnFlag.cancel) {
|
|
429
|
+
// Cancel further event processing
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return resultArr;
|
|
435
|
+
}
|
|
436
|
+
|
|
333
437
|
/**
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
438
|
+
* Call an event listener by name. The `rpc()` function differs from `emit()` in
|
|
439
|
+
* that it will only call and return data from the first event listener for the
|
|
440
|
+
* event rather than all event listeners. If you have more than one event listener
|
|
441
|
+
* assigned to the event, all others except the first will be ignored and will
|
|
442
|
+
* not receive the event.
|
|
443
|
+
* @param eventName The name of the event to call the listener for.
|
|
444
|
+
* @param {...any} data The arguments to send to the listening method.
|
|
337
445
|
* If you are sending multiple arguments, separate them with a comma so
|
|
338
446
|
* that they are received by the function as separate arguments.
|
|
339
447
|
* @return {number}
|
|
340
|
-
* @example #
|
|
448
|
+
* @example #Call the Event Listener
|
|
341
449
|
* // Emit the event named "hello"
|
|
342
450
|
* myEntity.emit('hello');
|
|
343
|
-
* @example #
|
|
451
|
+
* @example #Call the Event Listener With Data Object
|
|
344
452
|
* // Emit the event named "hello"
|
|
345
453
|
* myEntity.emit('hello', {moo: true});
|
|
346
|
-
* @example #
|
|
454
|
+
* @example #Call the Event Listener With Multiple Data Values
|
|
347
455
|
* // Emit the event named "hello"
|
|
348
456
|
* myEntity.emit('hello', {moo: true}, 'someString');
|
|
349
|
-
* @example #
|
|
457
|
+
* @example #Register the Listener for Event Data
|
|
350
458
|
* // Set a listener to listen for the data (multiple values emitted
|
|
351
459
|
* // from an event are passed as function arguments)
|
|
352
|
-
*
|
|
353
|
-
* console.log(arg1, arg2);
|
|
460
|
+
* myEntity.on('hello', function (arg1, arg2) {
|
|
461
|
+
* console.log("Arguments:", arg1, arg2);
|
|
462
|
+
* return "foo";
|
|
354
463
|
* }
|
|
355
464
|
*
|
|
356
465
|
* // Emit the event named "hello"
|
|
357
|
-
* myEntity.emit('hello', 'data1', 'data2');
|
|
466
|
+
* const result = myEntity.emit('hello', 'data1', 'data2');
|
|
467
|
+
* console.log("Result:", result);
|
|
358
468
|
*
|
|
359
469
|
* // The console output is:
|
|
360
|
-
* //
|
|
470
|
+
* // Arguments: data1 data2
|
|
471
|
+
* // Result: "foo"
|
|
361
472
|
*/
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
473
|
+
rpc<EventName extends keyof EventsInterface>(
|
|
474
|
+
eventName: EventName,
|
|
475
|
+
...data: Parameters<EventsInterface[EventName]>
|
|
476
|
+
): ReturnType<EventsInterface[EventName]> | ListenerReturnFlag {
|
|
477
|
+
return this.rpcId<EventName>(eventName, "*", ...data);
|
|
478
|
+
}
|
|
366
479
|
|
|
367
|
-
|
|
480
|
+
rpcId<EventName extends keyof EventsInterface>(
|
|
481
|
+
eventName: EventName,
|
|
482
|
+
id: string,
|
|
483
|
+
...data: Parameters<EventsInterface[EventName]>
|
|
484
|
+
): ReturnType<EventsInterface[EventName]> | ListenerReturnFlag {
|
|
485
|
+
if (!this._eventListeners || !this._eventListeners[eventName]) {
|
|
486
|
+
throw new Error("Cannot make an rpc call without at least one event listener and none were found");
|
|
487
|
+
}
|
|
368
488
|
|
|
369
|
-
let
|
|
489
|
+
let emitterResult: ReturnType<EventsInterface[EventName]> | ListenerReturnFlag;
|
|
370
490
|
this._eventsEmitting = true;
|
|
371
491
|
|
|
372
|
-
if (this._eventListeners[eventName]
|
|
373
|
-
// Handle
|
|
492
|
+
if (this._eventListeners[eventName]![id]) {
|
|
493
|
+
// Handle id emit
|
|
374
494
|
const arr = this._eventListeners[eventName]![id];
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
495
|
+
emitterResult = this._emitToSingleListener<EventName>(arr[0], data);
|
|
496
|
+
} else if (id !== "*" && this._eventListeners[eventName]!["*"]) {
|
|
497
|
+
// Handle global emit if the id passed wasn't already a global (*) id
|
|
498
|
+
const arr = this._eventListeners[eventName]!["*"];
|
|
499
|
+
emitterResult = this._emitToSingleListener<EventName>(arr[0], data);
|
|
500
|
+
} else {
|
|
501
|
+
if (id === "*") {
|
|
502
|
+
throw new Error(
|
|
503
|
+
`Cannot make an rpc call to event "${
|
|
504
|
+
eventName as string
|
|
505
|
+
}" without at least one event listener and none were found, register a listener via on("${
|
|
506
|
+
eventName as string
|
|
507
|
+
}", () => { ...some listener code })`
|
|
508
|
+
);
|
|
385
509
|
}
|
|
510
|
+
|
|
511
|
+
throw new Error(
|
|
512
|
+
`Cannot make an rpc call to event "${
|
|
513
|
+
eventName as string
|
|
514
|
+
}" and id "${id}" without at least one event listener and none were found, register a listener via on("${
|
|
515
|
+
eventName as string
|
|
516
|
+
}", "${id}", () => { ...some listener code })`
|
|
517
|
+
);
|
|
386
518
|
}
|
|
387
519
|
|
|
388
520
|
this._eventsEmitting = false;
|
|
389
521
|
this._processRemovalQueue();
|
|
390
522
|
|
|
391
|
-
return
|
|
523
|
+
return emitterResult;
|
|
392
524
|
}
|
|
393
525
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
526
|
+
/**
|
|
527
|
+
* Emit an event by name.
|
|
528
|
+
* @param eventName The name of the event to emit.
|
|
529
|
+
* @param {...any} data The arguments to send to any listening methods.
|
|
530
|
+
* If you are sending multiple arguments, separate them with a comma so
|
|
531
|
+
* that they are received by the function as separate arguments.
|
|
532
|
+
* @return {number}
|
|
533
|
+
* @example #Emit an Event
|
|
534
|
+
* // Emit the event named "hello"
|
|
535
|
+
* myEntity.emit('hello');
|
|
536
|
+
* @example #Emit an Event With Data Object
|
|
537
|
+
* // Emit the event named "hello"
|
|
538
|
+
* myEntity.emit('hello', {moo: true});
|
|
539
|
+
* @example #Emit an Event With Multiple Data Values
|
|
540
|
+
* // Emit the event named "hello"
|
|
541
|
+
* myEntity.emit('hello', {moo: true}, 'someString');
|
|
542
|
+
* @example #Listen for Event Data
|
|
543
|
+
* // Set a listener to listen for the data (multiple values emitted
|
|
544
|
+
* // from an event are passed as function arguments)
|
|
545
|
+
* myEntity.on('hello', function (arg1, arg2) {
|
|
546
|
+
* console.log("Arguments:", arg1, arg2);
|
|
547
|
+
* return "foo";
|
|
548
|
+
* }
|
|
549
|
+
*
|
|
550
|
+
* // Emit the event named "hello"
|
|
551
|
+
* // The result is returned as an array of all return values
|
|
552
|
+
* // from all the listeners for the event
|
|
553
|
+
* const result = myEntity.emit('hello', 'data1', 'data2');
|
|
554
|
+
* console.log("Result:", result);
|
|
555
|
+
*
|
|
556
|
+
* // The console output is:
|
|
557
|
+
* // Arguments: data1 data2
|
|
558
|
+
* // Result: ["foo"]
|
|
559
|
+
*/
|
|
560
|
+
emit<EventName extends keyof EventsInterface>(
|
|
561
|
+
eventName: EventName,
|
|
562
|
+
...data: Parameters<EventsInterface[EventName]>
|
|
563
|
+
): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] {
|
|
564
|
+
return this.emitId<EventName>(eventName, "*", ...data);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
emitId<EventName extends keyof EventsInterface>(
|
|
568
|
+
eventName: EventName,
|
|
569
|
+
id: string,
|
|
570
|
+
...data: Parameters<EventsInterface[EventName]>
|
|
571
|
+
): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] {
|
|
572
|
+
if (!this._eventListeners || !this._eventListeners[eventName]) {
|
|
573
|
+
return [];
|
|
397
574
|
}
|
|
398
575
|
|
|
399
|
-
|
|
576
|
+
let emitterResult: (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[] = [];
|
|
400
577
|
this._eventsEmitting = true;
|
|
401
578
|
|
|
402
|
-
if (!this._eventListeners[eventName]) {
|
|
403
|
-
this._eventsEmitting = false;
|
|
404
|
-
this._processRemovalQueue();
|
|
405
|
-
|
|
406
|
-
return EventReturnFlag.none;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
579
|
// Handle id emit
|
|
410
580
|
if (this._eventListeners[eventName]![id]) {
|
|
411
581
|
const arr = this._eventListeners[eventName]![id];
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
415
|
-
// Check we have a function to execute
|
|
416
|
-
const tmpFunc = arr[arrIndex];
|
|
417
|
-
|
|
418
|
-
if (typeof tmpFunc === "function") {
|
|
419
|
-
tmpFunc.call(this, ...data);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
582
|
+
emitterResult = emitterResult.concat(this._emitToArrayOfListeners<EventName>(arr, data));
|
|
422
583
|
}
|
|
423
584
|
|
|
424
|
-
// Handle global emit
|
|
425
|
-
if (this._eventListeners[eventName]!["*"]) {
|
|
585
|
+
// Handle global emit if the id passed wasn't already a global (*) id
|
|
586
|
+
if (id !== "*" && this._eventListeners[eventName]!["*"]) {
|
|
426
587
|
const arr = this._eventListeners[eventName]!["*"];
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
for (let arrIndex = 0; arrIndex < arrCount; arrIndex++) {
|
|
430
|
-
// Check we have a function to execute
|
|
431
|
-
const tmpFunc = arr[arrIndex];
|
|
432
|
-
|
|
433
|
-
if (typeof tmpFunc === "function") {
|
|
434
|
-
tmpFunc.call(this, ...data);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
588
|
+
emitterResult = emitterResult.concat(this._emitToArrayOfListeners<EventName>(arr, data));
|
|
437
589
|
}
|
|
438
590
|
|
|
439
591
|
this._eventsEmitting = false;
|
|
440
592
|
this._processRemovalQueue();
|
|
441
593
|
|
|
442
|
-
return
|
|
594
|
+
return emitterResult;
|
|
443
595
|
}
|
|
444
596
|
|
|
445
597
|
/**
|
|
@@ -451,7 +603,10 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
451
603
|
* @returns The emitter instance.
|
|
452
604
|
* @private
|
|
453
605
|
*/
|
|
454
|
-
emitStatic<EventName extends keyof EventsInterface>
|
|
606
|
+
emitStatic<EventName extends keyof EventsInterface>(
|
|
607
|
+
eventName: EventName,
|
|
608
|
+
...data: Parameters<EventsInterface[EventName]>
|
|
609
|
+
) {
|
|
455
610
|
const id = "*";
|
|
456
611
|
this._eventListeners = this._eventListeners || {};
|
|
457
612
|
this._eventsEmitting = true;
|
|
@@ -476,8 +631,8 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
476
631
|
this._eventStaticEmitters = this._eventStaticEmitters || {};
|
|
477
632
|
this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
|
|
478
633
|
this._eventStaticEmitters[eventName]!.push({
|
|
479
|
-
|
|
480
|
-
|
|
634
|
+
id: "*",
|
|
635
|
+
args: data
|
|
481
636
|
});
|
|
482
637
|
|
|
483
638
|
this._processRemovalQueue();
|
|
@@ -495,7 +650,11 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
495
650
|
* @returns The emitter instance.
|
|
496
651
|
* @private
|
|
497
652
|
*/
|
|
498
|
-
emitStaticId<EventName extends keyof EventsInterface>
|
|
653
|
+
emitStaticId<EventName extends keyof EventsInterface>(
|
|
654
|
+
eventName: EventName,
|
|
655
|
+
id: string,
|
|
656
|
+
...data: Parameters<EventsInterface[EventName]>
|
|
657
|
+
) {
|
|
499
658
|
if (!id) throw new Error("Missing id from emitId call!");
|
|
500
659
|
|
|
501
660
|
this._eventListeners = this._eventListeners || {};
|
|
@@ -539,7 +698,7 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
539
698
|
this._eventStaticEmitters[eventName] = this._eventStaticEmitters[eventName] || [];
|
|
540
699
|
this._eventStaticEmitters[eventName]!.push({
|
|
541
700
|
id,
|
|
542
|
-
|
|
701
|
+
args: data
|
|
543
702
|
});
|
|
544
703
|
|
|
545
704
|
this._processRemovalQueue();
|
|
@@ -553,7 +712,7 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
553
712
|
* @returns The emitter instance.
|
|
554
713
|
* @private
|
|
555
714
|
*/
|
|
556
|
-
cancelStatic<EventName extends keyof EventsInterface>
|
|
715
|
+
cancelStatic<EventName extends keyof EventsInterface>(eventName: EventName) {
|
|
557
716
|
this._eventStaticEmitters = this._eventStaticEmitters || {};
|
|
558
717
|
this._eventStaticEmitters[eventName] = [];
|
|
559
718
|
|
|
@@ -566,7 +725,7 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
566
725
|
* @returns True if one or more event listeners are registered for
|
|
567
726
|
* the event. False if none are found.
|
|
568
727
|
*/
|
|
569
|
-
willEmit<EventName extends keyof EventsInterface>
|
|
728
|
+
willEmit<EventName extends keyof EventsInterface>(eventName: EventName) {
|
|
570
729
|
const id = "*";
|
|
571
730
|
|
|
572
731
|
if (!this._eventListeners || !this._eventListeners[eventName]) {
|
|
@@ -595,7 +754,7 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
595
754
|
* @returns True if one or more event listeners are registered for
|
|
596
755
|
* the event. False if none are found.
|
|
597
756
|
*/
|
|
598
|
-
willEmitId<EventName extends keyof EventsInterface>
|
|
757
|
+
willEmitId<EventName extends keyof EventsInterface>(eventName: EventName, id: string) {
|
|
599
758
|
if (!this._eventListeners || !this._eventListeners[eventName]) {
|
|
600
759
|
return false;
|
|
601
760
|
}
|
|
@@ -643,7 +802,10 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
643
802
|
* @param {...any} data Optional arguments to emit with the event.
|
|
644
803
|
* @returns The emitter instance.
|
|
645
804
|
*/
|
|
646
|
-
deferEmit<EventName extends keyof EventsInterface>
|
|
805
|
+
deferEmit<EventName extends keyof EventsInterface>(
|
|
806
|
+
eventName: EventName,
|
|
807
|
+
...data: Parameters<EventsInterface[EventName]>
|
|
808
|
+
) {
|
|
647
809
|
if (!this._eventsAllowDefer) {
|
|
648
810
|
// Check for an existing timeout
|
|
649
811
|
this._eventsDeferTimeouts = this._eventsDeferTimeouts || {};
|
|
@@ -663,16 +825,25 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
663
825
|
return this;
|
|
664
826
|
}
|
|
665
827
|
|
|
828
|
+
/**
|
|
829
|
+
* Returns true if the result from an emit() call passed as the first
|
|
830
|
+
* argument contains a cancellation flag.
|
|
831
|
+
* @param resultArr
|
|
832
|
+
*/
|
|
833
|
+
didCancel(resultArr: (unknown | ListenerReturnFlag)[]) {
|
|
834
|
+
return resultArr.findIndex((result) => result === ListenerReturnFlag.cancel) > -1;
|
|
835
|
+
}
|
|
836
|
+
|
|
666
837
|
/**
|
|
667
838
|
* If events are cleared with the off() method while the event emitter is
|
|
668
839
|
* actively processing any events then the off() calls get added to a
|
|
669
840
|
* queue to be executed after the event emitter is finished. This stops
|
|
670
|
-
* errors that might occur by potentially
|
|
671
|
-
* the emitter is running through them. This method is called after
|
|
672
|
-
* event emitter is finished processing.
|
|
841
|
+
* errors that might occur by potentially mutating the event listener array
|
|
842
|
+
* while the emitter is running through them. This method is called after
|
|
843
|
+
* the event emitter is finished processing.
|
|
673
844
|
* @private
|
|
674
845
|
*/
|
|
675
|
-
_processRemovalQueue
|
|
846
|
+
_processRemovalQueue() {
|
|
676
847
|
if (!this._eventRemovalQueue || !this._eventRemovalQueue.length) {
|
|
677
848
|
return;
|
|
678
849
|
}
|
|
@@ -687,10 +858,10 @@ export class Emitter<EventsInterface extends EmitterEventsInterface = EmitterEve
|
|
|
687
858
|
}
|
|
688
859
|
}
|
|
689
860
|
|
|
690
|
-
export function makeEmitter
|
|
691
|
-
export function makeEmitter
|
|
692
|
-
export function makeEmitter
|
|
693
|
-
export function makeEmitter
|
|
861
|
+
export function makeEmitter(obj: AnyConstructor, prototypeMode: boolean): Emitter;
|
|
862
|
+
export function makeEmitter(obj: boolean): Emitter;
|
|
863
|
+
export function makeEmitter(obj: Record<string, unknown>, prototypeMode: boolean): Emitter;
|
|
864
|
+
export function makeEmitter(obj: any, prototypeMode?: any) {
|
|
694
865
|
let operateOnObject;
|
|
695
866
|
|
|
696
867
|
if (obj === undefined && prototypeMode === undefined) {
|
|
@@ -713,7 +884,9 @@ export function makeEmitter (obj: any, prototypeMode?: any) {
|
|
|
713
884
|
|
|
714
885
|
if (prototypeMode) {
|
|
715
886
|
if (obj.prototype === undefined) {
|
|
716
|
-
throw new Error(
|
|
887
|
+
throw new Error(
|
|
888
|
+
"Cannot modify prototype of passed object, it has no prototype property! Was it instantiated with the new operator correctly?"
|
|
889
|
+
);
|
|
717
890
|
}
|
|
718
891
|
|
|
719
892
|
operateOnObject = obj.prototype;
|
|
@@ -736,4 +909,4 @@ export function makeEmitter (obj: any, prototypeMode?: any) {
|
|
|
736
909
|
operateOnObject._processRemovalQueue = Emitter.prototype._processRemovalQueue;
|
|
737
910
|
|
|
738
911
|
return obj;
|
|
739
|
-
}
|
|
912
|
+
}
|