|
1 | | -type EventListener<T> = (data: T) => void; |
2 | | - |
3 | | -export class EventEmitter<T> { |
4 | | - private listeners: EventListener<T>[]; |
| 1 | +import type {EventListeners} from './types'; |
| 2 | + |
| 3 | +/** |
| 4 | + * Class for emitting events |
| 5 | + * @example |
| 6 | + * import {EventEmitter} from '@gravity-ui/uikit'; |
| 7 | + * |
| 8 | + * const emitter = new EventEmitter<{ |
| 9 | + * foobar: [string, number] |
| 10 | + * }>(); |
| 11 | + * |
| 12 | + * emitter.notify('foobar', ['foo', 0]); // returns "false", because there is no attached listeners yet |
| 13 | + * |
| 14 | + * const unsubscribe = emitter.subscribe('foobar', (a, b) => { |
| 15 | + * console.log(a, b); |
| 16 | + * }); |
| 17 | + * |
| 18 | + * emitter.notify('foobar', ['foo', 1]); // returns "true", because listener is appeared |
| 19 | + */ |
| 20 | +export class EventEmitter<T extends Record<string, unknown[]>> { |
| 21 | + private listeners: EventListeners<T>; |
5 | 22 |
|
6 | 23 | constructor() { |
7 | | - this.listeners = []; |
| 24 | + this.listeners = {}; |
8 | 25 | } |
9 | 26 |
|
10 | 27 | destroy() { |
11 | | - this.listeners = []; |
| 28 | + this.listeners = {}; |
12 | 29 | } |
13 | 30 |
|
14 | | - subscribe(listener: EventListener<T>) { |
| 31 | + subscribe<Event extends keyof T>(event: Event, listener: (...args: T[Event]) => void) { |
15 | 32 | if (typeof listener === 'function') { |
16 | | - this.listeners.push(listener); |
| 33 | + this.listeners[event] = (this.listeners[event] || []).concat(listener); |
17 | 34 | } |
18 | 35 |
|
19 | 36 | return () => { |
20 | | - this.listeners = this.listeners.filter( |
| 37 | + this.listeners[event] = this.listeners[event]?.filter( |
21 | 38 | (currentListener) => listener !== currentListener, |
22 | 39 | ); |
23 | 40 | }; |
24 | 41 | } |
25 | 42 |
|
26 | | - notify(data: T) { |
27 | | - if (this.listeners.length === 0) { |
| 43 | + notify<Event extends keyof T>(event: Event, data: T[Event]) { |
| 44 | + if (!this.listeners[event]?.length) { |
28 | 45 | return false; |
29 | 46 | } |
30 | 47 |
|
31 | | - for (const listener of this.listeners) { |
32 | | - listener(data); |
| 48 | + for (const listener of this.listeners[event]) { |
| 49 | + listener(...data); |
33 | 50 | } |
34 | 51 |
|
35 | 52 | return true; |
|
0 commit comments