source: frontend/node_modules/emittery/readme.md

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 11.3 KB
Line 
1# <img src="media/header.png" width="1000">
2
3> Simple and modern async event emitter
4
5[![Coverage Status](https://codecov.io/gh/sindresorhus/emittery/branch/master/graph/badge.svg)](https://codecov.io/gh/sindresorhus/emittery)
6[![](https://badgen.net/bundlephobia/minzip/emittery)](https://bundlephobia.com/result?p=emittery)
7
8It works in Node.js and the browser (using a bundler).
9
10Emitting events asynchronously is important for production code where you want the least amount of synchronous operations. Since JavaScript is single-threaded, no other code can run while doing synchronous operations. For Node.js, that means it will block other requests, defeating the strength of the platform, which is scalability through async. In the browser, a synchronous operation could potentially cause lags and block user interaction.
11
12## Install
13
14```
15$ npm install emittery
16```
17
18## Usage
19
20```js
21const Emittery = require('emittery');
22
23const emitter = new Emittery();
24
25emitter.on('🦄', data => {
26 console.log(data);
27});
28
29const myUnicorn = Symbol('🦄');
30
31emitter.on(myUnicorn, data => {
32 console.log(`Unicorns love ${data}`);
33});
34
35emitter.emit('🦄', '🌈'); // Will trigger printing '🌈'
36emitter.emit(myUnicorn, '🦋'); // Will trigger printing 'Unicorns love 🦋'
37```
38
39## API
40
41### eventName
42
43Emittery accepts strings and symbols as event names.
44
45Symbol event names can be used to avoid name collisions when your classes are extended, especially for internal events.
46
47### emitter = new Emittery()
48
49#### on(eventName | eventName[], listener)
50
51Subscribe to one or more events.
52
53Returns an unsubscribe method.
54
55Using the same listener multiple times for the same event will result in only one method call per emitted event.
56
57```js
58const Emittery = require('emittery');
59
60const emitter = new Emittery();
61
62emitter.on('🦄', data => {
63 console.log(data);
64});
65emitter.on(['🦄', '🐶'], data => {
66 console.log(data);
67});
68
69emitter.emit('🦄', '🌈'); // log => '🌈' x2
70emitter.emit('🐶', '🍖'); // log => '🍖'
71```
72
73##### Custom subscribable events
74
75Emittery exports some symbols which represent custom events that can be passed to `Emitter.on` and similar methods.
76
77- `Emittery.listenerAdded` - Fires when an event listener was added.
78- `Emittery.listenerRemoved` - Fires when an event listener was removed.
79
80```js
81const Emittery = require('emittery');
82
83const emitter = new Emittery();
84
85emitter.on(Emittery.listenerAdded, ({listener, eventName}) => {
86 console.log(listener);
87 //=> data => {}
88
89 console.log(eventName);
90 //=> '🦄'
91});
92
93emitter.on('🦄', data => {
94 // Handle data
95});
96```
97
98###### Listener data
99
100- `listener` - The listener that was added.
101- `eventName` - The name of the event that was added or removed if `.on()` or `.off()` was used, or `undefined` if `.onAny()` or `.offAny()` was used.
102
103Only events that are not of this type are able to trigger these events.
104
105##### listener(data)
106
107#### off(eventName | eventName[], listener)
108
109Remove one or more event subscriptions.
110
111```js
112const Emittery = require('emittery');
113
114const emitter = new Emittery();
115
116const listener = data => console.log(data);
117(async () => {
118 emitter.on(['🦄', '🐶', '🦊'], listener);
119 await emitter.emit('🦄', 'a');
120 await emitter.emit('🐶', 'b');
121 await emitter.emit('🦊', 'c');
122 emitter.off('🦄', listener);
123 emitter.off(['🐶', '🦊'], listener);
124 await emitter.emit('🦄', 'a'); // Nothing happens
125 await emitter.emit('🐶', 'b'); // Nothing happens
126 await emitter.emit('🦊', 'c'); // Nothing happens
127})();
128```
129
130##### listener(data)
131
132#### once(eventName | eventName[])
133
134Subscribe to one or more events only once. It will be unsubscribed after the first event.
135
136Returns a promise for the event data when `eventName` is emitted.
137
138```js
139const Emittery = require('emittery');
140
141const emitter = new Emittery();
142
143emitter.once('🦄').then(data => {
144 console.log(data);
145 //=> '🌈'
146});
147emitter.once(['🦄', '🐶']).then(data => {
148 console.log(data);
149});
150
151emitter.emit('🦄', '🌈'); // Log => '🌈' x2
152emitter.emit('🐶', '🍖'); // Nothing happens
153```
154
155#### events(eventName)
156
157Get an async iterator which buffers data each time an event is emitted.
158
159Call `return()` on the iterator to remove the subscription.
160
161```js
162const Emittery = require('emittery');
163
164const emitter = new Emittery();
165const iterator = emitter.events('🦄');
166
167emitter.emit('🦄', '🌈1'); // Buffered
168emitter.emit('🦄', '🌈2'); // Buffered
169
170iterator
171 .next()
172 .then(({value, done}) => {
173 // done === false
174 // value === '🌈1'
175 return iterator.next();
176 })
177 .then(({value, done}) => {
178 // done === false
179 // value === '🌈2'
180 // Revoke subscription
181 return iterator.return();
182 })
183 .then(({done}) => {
184 // done === true
185 });
186```
187
188In practice, you would usually consume the events using the [for await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) statement. In that case, to revoke the subscription simply break the loop.
189
190```js
191const Emittery = require('emittery');
192
193const emitter = new Emittery();
194const iterator = emitter.events('🦄');
195
196emitter.emit('🦄', '🌈1'); // Buffered
197emitter.emit('🦄', '🌈2'); // Buffered
198
199// In an async context.
200for await (const data of iterator) {
201 if (data === '🌈2') {
202 break; // Revoke the subscription when we see the value '🌈2'.
203 }
204}
205```
206
207It accepts multiple event names.
208
209```js
210const Emittery = require('emittery');
211
212const emitter = new Emittery();
213const iterator = emitter.events(['🦄', '🦊']);
214
215emitter.emit('🦄', '🌈1'); // Buffered
216emitter.emit('🦊', '🌈2'); // Buffered
217
218iterator
219 .next()
220 .then(({value, done}) => {
221 // done === false
222 // value === '🌈1'
223 return iterator.next();
224 })
225 .then(({value, done}) => {
226 // done === false
227 // value === '🌈2'
228 // Revoke subscription
229 return iterator.return();
230 })
231 .then(({done}) => {
232 // done === true
233 });
234```
235
236#### emit(eventName, data?)
237
238Trigger an event asynchronously, optionally with some data. Listeners are called in the order they were added, but executed concurrently.
239
240Returns a promise that resolves when all the event listeners are done. *Done* meaning executed if synchronous or resolved when an async/promise-returning function. You usually wouldn't want to wait for this, but you could for example catch possible errors. If any of the listeners throw/reject, the returned promise will be rejected with the error, but the other listeners will not be affected.
241
242#### emitSerial(eventName, data?)
243
244Same as above, but it waits for each listener to resolve before triggering the next one. This can be useful if your events depend on each other. Although ideally they should not. Prefer `emit()` whenever possible.
245
246If any of the listeners throw/reject, the returned promise will be rejected with the error and the remaining listeners will *not* be called.
247
248#### onAny(listener)
249
250Subscribe to be notified about any event.
251
252Returns a method to unsubscribe.
253
254##### listener(eventName, data)
255
256#### offAny(listener)
257
258Remove an `onAny` subscription.
259
260#### anyEvent()
261
262Get an async iterator which buffers a tuple of an event name and data each time an event is emitted.
263
264Call `return()` on the iterator to remove the subscription.
265
266```js
267const Emittery = require('emittery');
268
269const emitter = new Emittery();
270const iterator = emitter.anyEvent();
271
272emitter.emit('🦄', '🌈1'); // Buffered
273emitter.emit('🌟', '🌈2'); // Buffered
274
275iterator.next()
276 .then(({value, done}) => {
277 // done === false
278 // value is ['🦄', '🌈1']
279 return iterator.next();
280 })
281 .then(({value, done}) => {
282 // done === false
283 // value is ['🌟', '🌈2']
284 // Revoke subscription
285 return iterator.return();
286 })
287 .then(({done}) => {
288 // done === true
289 });
290```
291
292In the same way as for `events`, you can subscribe by using the `for await` statement
293
294#### clearListeners(eventNames?)
295
296Clear all event listeners on the instance.
297
298If `eventNames` is given, only the listeners for that events are cleared.
299
300#### listenerCount(eventNames?)
301
302The number of listeners for the `eventNames` or all events if not specified.
303
304#### bindMethods(target, methodNames?)
305
306Bind the given `methodNames`, or all `Emittery` methods if `methodNames` is not defined, into the `target` object.
307
308```js
309import Emittery = require('emittery');
310
311const object = {};
312
313new Emittery().bindMethods(object);
314
315object.emit('event');
316```
317
318## TypeScript
319
320The default `Emittery` class has generic types that can be provided by TypeScript users to strongly type the list of events and the data passed to their event listeners.
321
322```ts
323import Emittery = require('emittery');
324
325const emitter = new Emittery<
326 // Pass `{[eventName]: undefined | <eventArg>}` as the first type argument for events that pass data to their listeners.
327 // A value of `undefined` in this map means the event listeners should expect no data, and a type other than `undefined` means the listeners will receive one argument of that type.
328 {
329 open: string,
330 close: undefined
331 }
332>();
333
334// Typechecks just fine because the data type for the `open` event is `string`.
335emitter.emit('open', 'foo\n');
336
337// Typechecks just fine because `close` is present but points to undefined in the event data type map.
338emitter.emit('close');
339
340// TS compilation error because `1` isn't assignable to `string`.
341emitter.emit('open', 1);
342
343// TS compilation error because `other` isn't defined in the event data type map.
344emitter.emit('other');
345```
346
347### Emittery.mixin(emitteryPropertyName, methodNames?)
348
349A decorator which mixins `Emittery` as property `emitteryPropertyName` and `methodNames`, or all `Emittery` methods if `methodNames` is not defined, into the target class.
350
351```ts
352import Emittery = require('emittery');
353
354@Emittery.mixin('emittery')
355class MyClass {}
356
357const instance = new MyClass();
358
359instance.emit('event');
360```
361
362## Scheduling details
363
364Listeners are not invoked for events emitted *before* the listener was added. Removing a listener will prevent that listener from being invoked, even if events are in the process of being (asynchronously!) emitted. This also applies to `.clearListeners()`, which removes all listeners. Listeners will be called in the order they were added. So-called *any* listeners are called *after* event-specific listeners.
365
366Note that when using `.emitSerial()`, a slow listener will delay invocation of subsequent listeners. It's possible for newer events to overtake older ones.
367
368## FAQ
369
370### How is this different than the built-in `EventEmitter` in Node.js?
371
372There are many things to not like about `EventEmitter`: its huge API surface, synchronous event emitting, magic error event, flawed memory leak detection. Emittery has none of that.
373
374### Isn't `EventEmitter` synchronous for a reason?
375
376Mostly backwards compatibility reasons. The Node.js team can't break the whole ecosystem.
377
378It also allows silly code like this:
379
380```js
381let unicorn = false;
382
383emitter.on('🦄', () => {
384 unicorn = true;
385});
386
387emitter.emit('🦄');
388
389console.log(unicorn);
390//=> true
391```
392
393But I would argue doing that shows a deeper lack of Node.js and async comprehension and is not something we should optimize for. The benefit of async emitting is much greater.
394
395### Can you support multiple arguments for `emit()`?
396
397No, just use [destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment):
398
399```js
400emitter.on('🦄', ([foo, bar]) => {
401 console.log(foo, bar);
402});
403
404emitter.emit('🦄', [foo, bar]);
405```
406
407## Related
408
409- [p-event](https://github.com/sindresorhus/p-event) - Promisify an event by waiting for it to be emitted
Note: See TracBrowser for help on using the repository browser.