UNPKG

3.01 kBJavaScriptView Raw
1import "core-js/modules/web.immediate.js";
2import deprecate from 'util-deprecate';
3import dedent from 'ts-dedent';
4
5const generateRandomId = () => {
6 // generates a random 13 character string
7 return Math.random().toString(16).slice(2);
8};
9
10export class Channel {
11 constructor({
12 transport,
13 async = false
14 } = {}) {
15 this.isAsync = void 0;
16 this.sender = generateRandomId();
17 this.events = {};
18 this.data = {};
19 this.transport = void 0;
20 this.addPeerListener = deprecate((eventName, listener) => {
21 this.addListener(eventName, listener);
22 }, dedent`
23 channel.addPeerListener is deprecated
24 `);
25 this.isAsync = async;
26
27 if (transport) {
28 this.transport = transport;
29 this.transport.setHandler(event => this.handleEvent(event));
30 }
31 }
32
33 get hasTransport() {
34 return !!this.transport;
35 }
36
37 addListener(eventName, listener) {
38 this.events[eventName] = this.events[eventName] || [];
39 this.events[eventName].push(listener);
40 }
41
42 emit(eventName, ...args) {
43 const event = {
44 type: eventName,
45 args,
46 from: this.sender
47 };
48 let options = {};
49
50 if (args.length >= 1 && args[0] && args[0].options) {
51 options = args[0].options;
52 }
53
54 const handler = () => {
55 if (this.transport) {
56 this.transport.send(event, options);
57 }
58
59 this.handleEvent(event);
60 };
61
62 if (this.isAsync) {
63 // todo I'm not sure how to test this
64 setImmediate(handler);
65 } else {
66 handler();
67 }
68 }
69
70 last(eventName) {
71 return this.data[eventName];
72 }
73
74 eventNames() {
75 return Object.keys(this.events);
76 }
77
78 listenerCount(eventName) {
79 const listeners = this.listeners(eventName);
80 return listeners ? listeners.length : 0;
81 }
82
83 listeners(eventName) {
84 const listeners = this.events[eventName];
85 return listeners || undefined;
86 }
87
88 once(eventName, listener) {
89 const onceListener = this.onceListener(eventName, listener);
90 this.addListener(eventName, onceListener);
91 }
92
93 removeAllListeners(eventName) {
94 if (!eventName) {
95 this.events = {};
96 } else if (this.events[eventName]) {
97 delete this.events[eventName];
98 }
99 }
100
101 removeListener(eventName, listener) {
102 const listeners = this.listeners(eventName);
103
104 if (listeners) {
105 this.events[eventName] = listeners.filter(l => l !== listener);
106 }
107 }
108
109 on(eventName, listener) {
110 this.addListener(eventName, listener);
111 }
112
113 off(eventName, listener) {
114 this.removeListener(eventName, listener);
115 }
116
117 handleEvent(event) {
118 const listeners = this.listeners(event.type);
119
120 if (listeners && listeners.length) {
121 listeners.forEach(fn => {
122 fn.apply(event, event.args);
123 });
124 }
125
126 this.data[event.type] = event.args;
127 }
128
129 onceListener(eventName, listener) {
130 const onceListener = (...args) => {
131 this.removeListener(eventName, onceListener);
132 return listener(...args);
133 };
134
135 return onceListener;
136 }
137
138}
139export default Channel;
\No newline at end of file