emittery 0.6.0 → 0.7.0
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/index.d.ts +99 -9
- package/index.js +80 -52
- package/package.json +1 -1
- package/readme.md +79 -11
package/index.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ Symbol event names can be used to avoid name collisions when your classes are ex
|
|
|
5
5
|
*/
|
|
6
6
|
type EventName = string | symbol;
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
Emittery also accepts an array of strings and symbols as event names.
|
|
10
|
+
*/
|
|
11
|
+
type EventNames = EventName | readonly EventName[];
|
|
12
|
+
|
|
8
13
|
declare class Emittery {
|
|
9
14
|
/**
|
|
10
15
|
In TypeScript, it returns a decorator which mixins `Emittery` as property `emitteryPropertyName` and `methodNames`, or all `Emittery` methods if `methodNames` is not defined, into the target class.
|
|
@@ -78,14 +83,31 @@ declare class Emittery {
|
|
|
78
83
|
static readonly listenerRemoved: unique symbol;
|
|
79
84
|
|
|
80
85
|
/**
|
|
81
|
-
Subscribe to
|
|
86
|
+
Subscribe to one or more events.
|
|
82
87
|
|
|
83
88
|
Using the same listener multiple times for the same event will result in only one method call per emitted event.
|
|
84
89
|
|
|
85
90
|
@returns An unsubscribe method.
|
|
91
|
+
|
|
92
|
+
@example
|
|
93
|
+
```
|
|
94
|
+
import Emittery = require('emittery');
|
|
95
|
+
|
|
96
|
+
const emitter = new Emittery();
|
|
97
|
+
|
|
98
|
+
emitter.on('🦄', data => {
|
|
99
|
+
console.log(data);
|
|
100
|
+
});
|
|
101
|
+
emitter.on(['🦄', '🐶'], data => {
|
|
102
|
+
console.log(data);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
emitter.emit('🦄', '🌈'); // log => '🌈' x2
|
|
106
|
+
emitter.emit('🐶', '🍖'); // log => '🍖'
|
|
107
|
+
```
|
|
86
108
|
*/
|
|
87
109
|
on(eventName: typeof Emittery.listenerAdded | typeof Emittery.listenerRemoved, listener: (eventData: Emittery.ListenerChangedData) => void): Emittery.UnsubscribeFn
|
|
88
|
-
on(eventName:
|
|
110
|
+
on(eventName: EventNames, listener: (eventData?: unknown) => void): Emittery.UnsubscribeFn;
|
|
89
111
|
|
|
90
112
|
/**
|
|
91
113
|
Get an async iterator which buffers data each time an event is emitted.
|
|
@@ -139,22 +161,90 @@ declare class Emittery {
|
|
|
139
161
|
}
|
|
140
162
|
}
|
|
141
163
|
```
|
|
164
|
+
|
|
165
|
+
It accepts multiple event names.
|
|
166
|
+
|
|
167
|
+
@example
|
|
168
|
+
```
|
|
169
|
+
import Emittery = require('emittery');
|
|
170
|
+
|
|
171
|
+
const emitter = new Emittery();
|
|
172
|
+
const iterator = emitter.events(['🦄', '🦊']);
|
|
173
|
+
|
|
174
|
+
emitter.emit('🦄', '🌈1'); // Buffered
|
|
175
|
+
emitter.emit('🦊', '🌈2'); // Buffered
|
|
176
|
+
|
|
177
|
+
iterator
|
|
178
|
+
.next()
|
|
179
|
+
.then(({value, done}) => {
|
|
180
|
+
// done === false
|
|
181
|
+
// value === '🌈1'
|
|
182
|
+
return iterator.next();
|
|
183
|
+
})
|
|
184
|
+
.then(({value, done}) => {
|
|
185
|
+
// done === false
|
|
186
|
+
// value === '🌈2'
|
|
187
|
+
// Revoke subscription
|
|
188
|
+
return iterator.return();
|
|
189
|
+
})
|
|
190
|
+
.then(({done}) => {
|
|
191
|
+
// done === true
|
|
192
|
+
});
|
|
193
|
+
```
|
|
142
194
|
*/
|
|
143
|
-
events(eventName:
|
|
195
|
+
events(eventName: EventNames): AsyncIterableIterator<unknown>
|
|
144
196
|
|
|
145
197
|
/**
|
|
146
|
-
Remove
|
|
198
|
+
Remove one or more event subscriptions.
|
|
199
|
+
|
|
200
|
+
@example
|
|
201
|
+
```
|
|
202
|
+
import Emittery = require('emittery');
|
|
203
|
+
|
|
204
|
+
const emitter = new Emittery();
|
|
205
|
+
|
|
206
|
+
const listener = data => console.log(data);
|
|
207
|
+
(async () => {
|
|
208
|
+
emitter.on(['🦄', '🐶', '🦊'], listener);
|
|
209
|
+
await emitter.emit('🦄', 'a');
|
|
210
|
+
await emitter.emit('🐶', 'b');
|
|
211
|
+
await emitter.emit('🦊', 'c');
|
|
212
|
+
emitter.off('🦄', listener);
|
|
213
|
+
emitter.off(['🐶', '🦊'], listener);
|
|
214
|
+
await emitter.emit('🦄', 'a'); // nothing happens
|
|
215
|
+
await emitter.emit('🐶', 'b'); // nothing happens
|
|
216
|
+
await emitter.emit('🦊', 'c'); // nothing happens
|
|
217
|
+
})();
|
|
218
|
+
```
|
|
147
219
|
*/
|
|
148
|
-
off(eventName:
|
|
220
|
+
off(eventName: EventNames, listener: (eventData?: unknown) => void): void;
|
|
149
221
|
|
|
150
222
|
/**
|
|
151
|
-
Subscribe to
|
|
223
|
+
Subscribe to one or more events only once. It will be unsubscribed after the first
|
|
152
224
|
event.
|
|
153
225
|
|
|
154
226
|
@returns The event data when `eventName` is emitted.
|
|
227
|
+
|
|
228
|
+
@example
|
|
229
|
+
```
|
|
230
|
+
import Emittery = require('emittery');
|
|
231
|
+
|
|
232
|
+
const emitter = new Emittery();
|
|
233
|
+
|
|
234
|
+
emitter.once('🦄').then(data => {
|
|
235
|
+
console.log(data);
|
|
236
|
+
//=> '🌈'
|
|
237
|
+
});
|
|
238
|
+
emitter.once(['🦄', '🐶']).then(data => {
|
|
239
|
+
console.log(data);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
emitter.emit('🦄', '🌈'); // Logs `🌈` twice
|
|
243
|
+
emitter.emit('🐶', '🍖'); // Nothing happens
|
|
244
|
+
```
|
|
155
245
|
*/
|
|
156
246
|
once(eventName: typeof Emittery.listenerAdded | typeof Emittery.listenerRemoved): Promise<Emittery.ListenerChangedData>
|
|
157
|
-
once(eventName:
|
|
247
|
+
once(eventName: EventNames): Promise<unknown>;
|
|
158
248
|
|
|
159
249
|
/**
|
|
160
250
|
Trigger an event asynchronously, optionally with some data. Listeners are called in the order they were added, but executed concurrently.
|
|
@@ -225,12 +315,12 @@ declare class Emittery {
|
|
|
225
315
|
|
|
226
316
|
If `eventName` is given, only the listeners for that event are cleared.
|
|
227
317
|
*/
|
|
228
|
-
clearListeners(eventName?:
|
|
318
|
+
clearListeners(eventName?: EventNames): void;
|
|
229
319
|
|
|
230
320
|
/**
|
|
231
321
|
The number of listeners for the `eventName` or all events if not specified.
|
|
232
322
|
*/
|
|
233
|
-
listenerCount(eventName?:
|
|
323
|
+
listenerCount(eventName?: EventNames): number;
|
|
234
324
|
|
|
235
325
|
/**
|
|
236
326
|
Bind the given `methodNames`, or all `Emittery` methods if `methodNames` is not defined, into the `target` object.
|
package/index.js
CHANGED
|
@@ -56,7 +56,9 @@ function enqueueProducers(instance, eventName, eventData) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function iterator(instance,
|
|
59
|
+
function iterator(instance, eventNames) {
|
|
60
|
+
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
61
|
+
|
|
60
62
|
let isFinished = false;
|
|
61
63
|
let flush = () => {};
|
|
62
64
|
let queue = [];
|
|
@@ -72,7 +74,9 @@ function iterator(instance, eventName) {
|
|
|
72
74
|
}
|
|
73
75
|
};
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
for (const eventName of eventNames) {
|
|
78
|
+
getEventProducers(instance, eventName).add(producer);
|
|
79
|
+
}
|
|
76
80
|
|
|
77
81
|
return {
|
|
78
82
|
async next() {
|
|
@@ -101,7 +105,11 @@ function iterator(instance, eventName) {
|
|
|
101
105
|
|
|
102
106
|
async return(value) {
|
|
103
107
|
queue = undefined;
|
|
104
|
-
|
|
108
|
+
|
|
109
|
+
for (const eventName of eventNames) {
|
|
110
|
+
getEventProducers(instance, eventName).delete(producer);
|
|
111
|
+
}
|
|
112
|
+
|
|
105
113
|
flush();
|
|
106
114
|
|
|
107
115
|
return arguments.length > 0 ?
|
|
@@ -187,42 +195,52 @@ class Emittery {
|
|
|
187
195
|
producersMap.set(this, new Map());
|
|
188
196
|
}
|
|
189
197
|
|
|
190
|
-
on(
|
|
191
|
-
assertEventName(eventName);
|
|
198
|
+
on(eventNames, listener) {
|
|
192
199
|
assertListener(listener);
|
|
193
|
-
getListeners(this, eventName).add(listener);
|
|
194
200
|
|
|
195
|
-
|
|
196
|
-
|
|
201
|
+
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
202
|
+
for (const eventName of eventNames) {
|
|
203
|
+
assertEventName(eventName);
|
|
204
|
+
getListeners(this, eventName).add(listener);
|
|
205
|
+
|
|
206
|
+
if (!isListenerSymbol(eventName)) {
|
|
207
|
+
this.emit(listenerAdded, {eventName, listener});
|
|
208
|
+
}
|
|
197
209
|
}
|
|
198
210
|
|
|
199
|
-
return this.off.bind(this,
|
|
211
|
+
return this.off.bind(this, eventNames, listener);
|
|
200
212
|
}
|
|
201
213
|
|
|
202
|
-
off(
|
|
203
|
-
assertEventName(eventName);
|
|
214
|
+
off(eventNames, listener) {
|
|
204
215
|
assertListener(listener);
|
|
205
216
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
217
|
+
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
218
|
+
for (const eventName of eventNames) {
|
|
219
|
+
assertEventName(eventName);
|
|
220
|
+
getListeners(this, eventName).delete(listener);
|
|
209
221
|
|
|
210
|
-
|
|
222
|
+
if (!isListenerSymbol(eventName)) {
|
|
223
|
+
this.emit(listenerRemoved, {eventName, listener});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
211
226
|
}
|
|
212
227
|
|
|
213
|
-
once(
|
|
228
|
+
once(eventNames) {
|
|
214
229
|
return new Promise(resolve => {
|
|
215
|
-
|
|
216
|
-
const off = this.on(eventName, data => {
|
|
230
|
+
const off = this.on(eventNames, data => {
|
|
217
231
|
off();
|
|
218
232
|
resolve(data);
|
|
219
233
|
});
|
|
220
234
|
});
|
|
221
235
|
}
|
|
222
236
|
|
|
223
|
-
events(
|
|
224
|
-
|
|
225
|
-
|
|
237
|
+
events(eventNames) {
|
|
238
|
+
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
239
|
+
for (const eventName of eventNames) {
|
|
240
|
+
assertEventName(eventName);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return iterator(this, eventNames);
|
|
226
244
|
}
|
|
227
245
|
|
|
228
246
|
async emit(eventName, eventData) {
|
|
@@ -236,7 +254,7 @@ class Emittery {
|
|
|
236
254
|
const staticAnyListeners = isListenerSymbol(eventName) ? [] : [...anyListeners];
|
|
237
255
|
|
|
238
256
|
await resolvedPromise;
|
|
239
|
-
|
|
257
|
+
await Promise.all([
|
|
240
258
|
...staticListeners.map(async listener => {
|
|
241
259
|
if (listeners.has(listener)) {
|
|
242
260
|
return listener(eventData);
|
|
@@ -291,52 +309,62 @@ class Emittery {
|
|
|
291
309
|
anyMap.get(this).delete(listener);
|
|
292
310
|
}
|
|
293
311
|
|
|
294
|
-
clearListeners(
|
|
295
|
-
|
|
296
|
-
getListeners(this, eventName).clear();
|
|
312
|
+
clearListeners(eventNames) {
|
|
313
|
+
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
297
314
|
|
|
298
|
-
|
|
315
|
+
for (const eventName of eventNames) {
|
|
316
|
+
if (typeof eventName === 'string') {
|
|
317
|
+
getListeners(this, eventName).clear();
|
|
299
318
|
|
|
300
|
-
|
|
301
|
-
producer.finish();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
producers.clear();
|
|
305
|
-
} else {
|
|
306
|
-
anyMap.get(this).clear();
|
|
319
|
+
const producers = getEventProducers(this, eventName);
|
|
307
320
|
|
|
308
|
-
for (const listeners of eventsMap.get(this).values()) {
|
|
309
|
-
listeners.clear();
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
for (const producers of producersMap.get(this).values()) {
|
|
313
321
|
for (const producer of producers) {
|
|
314
322
|
producer.finish();
|
|
315
323
|
}
|
|
316
324
|
|
|
317
325
|
producers.clear();
|
|
326
|
+
} else {
|
|
327
|
+
anyMap.get(this).clear();
|
|
328
|
+
|
|
329
|
+
for (const listeners of eventsMap.get(this).values()) {
|
|
330
|
+
listeners.clear();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
for (const producers of producersMap.get(this).values()) {
|
|
334
|
+
for (const producer of producers) {
|
|
335
|
+
producer.finish();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
producers.clear();
|
|
339
|
+
}
|
|
318
340
|
}
|
|
319
341
|
}
|
|
320
342
|
}
|
|
321
343
|
|
|
322
|
-
listenerCount(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
getEventProducers(this, eventName).size + getEventProducers(this).size;
|
|
326
|
-
}
|
|
344
|
+
listenerCount(eventNames) {
|
|
345
|
+
eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
346
|
+
let count = 0;
|
|
327
347
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
348
|
+
for (const eventName of eventNames) {
|
|
349
|
+
if (typeof eventName === 'string') {
|
|
350
|
+
count += anyMap.get(this).size + getListeners(this, eventName).size +
|
|
351
|
+
getEventProducers(this, eventName).size + getEventProducers(this).size;
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
331
354
|
|
|
332
|
-
|
|
355
|
+
if (typeof eventName !== 'undefined') {
|
|
356
|
+
assertEventName(eventName);
|
|
357
|
+
}
|
|
333
358
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
359
|
+
count += anyMap.get(this).size;
|
|
360
|
+
|
|
361
|
+
for (const value of eventsMap.get(this).values()) {
|
|
362
|
+
count += value.size;
|
|
363
|
+
}
|
|
337
364
|
|
|
338
|
-
|
|
339
|
-
|
|
365
|
+
for (const value of producersMap.get(this).values()) {
|
|
366
|
+
count += value.size;
|
|
367
|
+
}
|
|
340
368
|
}
|
|
341
369
|
|
|
342
370
|
return count;
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -45,14 +45,30 @@ Symbol event names can be used to avoid name collisions when your classes are ex
|
|
|
45
45
|
|
|
46
46
|
### emitter = new Emittery()
|
|
47
47
|
|
|
48
|
-
#### on(eventName, listener)
|
|
48
|
+
#### on(eventName | eventName[], listener)
|
|
49
49
|
|
|
50
|
-
Subscribe to
|
|
50
|
+
Subscribe to one or more events.
|
|
51
51
|
|
|
52
52
|
Returns an unsubscribe method.
|
|
53
53
|
|
|
54
54
|
Using the same listener multiple times for the same event will result in only one method call per emitted event.
|
|
55
55
|
|
|
56
|
+
```js
|
|
57
|
+
const Emittery = require('emittery');
|
|
58
|
+
|
|
59
|
+
const emitter = new Emittery();
|
|
60
|
+
|
|
61
|
+
emitter.on('🦄', data => {
|
|
62
|
+
console.log(data);
|
|
63
|
+
});
|
|
64
|
+
emitter.on(['🦄', '🐶'], data => {
|
|
65
|
+
console.log(data);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
emitter.emit('🦄', '🌈'); // log => '🌈' x2
|
|
69
|
+
emitter.emit('🐶', '🍖'); // log => '🍖'
|
|
70
|
+
```
|
|
71
|
+
|
|
56
72
|
##### Custom subscribable events
|
|
57
73
|
|
|
58
74
|
Emittery exports some symbols which represent custom events that can be passed to `Emitter.on` and similar methods.
|
|
@@ -87,15 +103,34 @@ Only events that are not of this type are able to trigger these events.
|
|
|
87
103
|
|
|
88
104
|
##### listener(data)
|
|
89
105
|
|
|
90
|
-
#### off(eventName, listener)
|
|
106
|
+
#### off(eventName | eventName[], listener)
|
|
107
|
+
|
|
108
|
+
Remove one or more event subscriptions.
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
const Emittery = require('emittery');
|
|
112
|
+
|
|
113
|
+
const emitter = new Emittery();
|
|
91
114
|
|
|
92
|
-
|
|
115
|
+
const listener = data => console.log(data);
|
|
116
|
+
(async () => {
|
|
117
|
+
emitter.on(['🦄', '🐶', '🦊'], listener);
|
|
118
|
+
await emitter.emit('🦄', 'a');
|
|
119
|
+
await emitter.emit('🐶', 'b');
|
|
120
|
+
await emitter.emit('🦊', 'c');
|
|
121
|
+
emitter.off('🦄', listener);
|
|
122
|
+
emitter.off(['🐶', '🦊'], listener);
|
|
123
|
+
await emitter.emit('🦄', 'a'); // nothing happens
|
|
124
|
+
await emitter.emit('🐶', 'b'); // nothing happens
|
|
125
|
+
await emitter.emit('🦊', 'c'); // nothing happens
|
|
126
|
+
})();
|
|
127
|
+
```
|
|
93
128
|
|
|
94
129
|
##### listener(data)
|
|
95
130
|
|
|
96
|
-
#### once(eventName)
|
|
131
|
+
#### once(eventName | eventName[])
|
|
97
132
|
|
|
98
|
-
Subscribe to
|
|
133
|
+
Subscribe to one or more events only once. It will be unsubscribed after the first event.
|
|
99
134
|
|
|
100
135
|
Returns a promise for the event data when `eventName` is emitted.
|
|
101
136
|
|
|
@@ -108,8 +143,12 @@ emitter.once('🦄').then(data => {
|
|
|
108
143
|
console.log(data);
|
|
109
144
|
//=> '🌈'
|
|
110
145
|
});
|
|
146
|
+
emitter.once(['🦄', '🐶']).then(data => {
|
|
147
|
+
console.log(data);
|
|
148
|
+
});
|
|
111
149
|
|
|
112
|
-
emitter.emit('🦄', '🌈');
|
|
150
|
+
emitter.emit('🦄', '🌈'); // log => '🌈' x2
|
|
151
|
+
emitter.emit('🐶', '🍖'); // nothing happens
|
|
113
152
|
```
|
|
114
153
|
|
|
115
154
|
#### events(eventName)
|
|
@@ -164,6 +203,35 @@ for await (const data of iterator) {
|
|
|
164
203
|
}
|
|
165
204
|
```
|
|
166
205
|
|
|
206
|
+
It accepts multiple event names.
|
|
207
|
+
|
|
208
|
+
```js
|
|
209
|
+
const Emittery = require('emittery');
|
|
210
|
+
|
|
211
|
+
const emitter = new Emittery();
|
|
212
|
+
const iterator = emitter.events(['🦄', '🦊']);
|
|
213
|
+
|
|
214
|
+
emitter.emit('🦄', '🌈1'); // Buffered
|
|
215
|
+
emitter.emit('🦊', '🌈2'); // Buffered
|
|
216
|
+
|
|
217
|
+
iterator
|
|
218
|
+
.next()
|
|
219
|
+
.then(({value, done}) => {
|
|
220
|
+
// done === false
|
|
221
|
+
// value === '🌈1'
|
|
222
|
+
return iterator.next();
|
|
223
|
+
})
|
|
224
|
+
.then(({value, done}) => {
|
|
225
|
+
// done === false
|
|
226
|
+
// value === '🌈2'
|
|
227
|
+
// Revoke subscription
|
|
228
|
+
return iterator.return();
|
|
229
|
+
})
|
|
230
|
+
.then(({done}) => {
|
|
231
|
+
// done === true
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
167
235
|
#### emit(eventName, data?)
|
|
168
236
|
|
|
169
237
|
Trigger an event asynchronously, optionally with some data. Listeners are called in the order they were added, but executed concurrently.
|
|
@@ -222,15 +290,15 @@ iterator.next()
|
|
|
222
290
|
|
|
223
291
|
In the same way as for `events`, you can subscribe by using the `for await` statement
|
|
224
292
|
|
|
225
|
-
#### clearListeners()
|
|
293
|
+
#### clearListeners(eventNames?)
|
|
226
294
|
|
|
227
295
|
Clear all event listeners on the instance.
|
|
228
296
|
|
|
229
|
-
If `
|
|
297
|
+
If `eventNames` is given, only the listeners for that events are cleared.
|
|
230
298
|
|
|
231
|
-
#### listenerCount(
|
|
299
|
+
#### listenerCount(eventNames?)
|
|
232
300
|
|
|
233
|
-
The number of listeners for the `
|
|
301
|
+
The number of listeners for the `eventNames` or all events if not specified.
|
|
234
302
|
|
|
235
303
|
#### bindMethods(target, methodNames?)
|
|
236
304
|
|