Skip to content

Commit 15972ae

Browse files
committed
feat: rewritten lib
1 parent d8639ac commit 15972ae

8 files changed

+762
-380
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
/.idea
2+
/dist
23
/node_modules
3-
/*.js

index.ts

+364-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,365 @@
1-
import Websocket from "./src/Websocket";
1+
class RTC_Event {
2+
listeners: {};
23

3-
const ws = new Websocket('');
4+
constructor() {
5+
this.listeners = {
6+
'on': {},
7+
'once': {}
8+
}
9+
}
10+
11+
on(name: string, listener: CallableFunction): void {
12+
if (!this.listeners['on'][name]) {
13+
this.listeners['on'][name] = [];
14+
}
15+
16+
this.listeners['on'][name].push(listener);
17+
}
18+
19+
once(name: string, listener: CallableFunction): void {
20+
if (!this.listeners['once'][name]) {
21+
this.listeners['once'][name] = [];
22+
}
23+
24+
this.listeners['once'][name].push(listener);
25+
}
26+
27+
dispatch(name: string, data: any[] = []): void {
28+
let regularEvent = this.listeners['on'];
29+
if (regularEvent.hasOwnProperty(name)) {
30+
regularEvent[name].forEach(function (listener) {
31+
listener(...data)
32+
});
33+
}
34+
35+
let onceEvent = this.listeners['once'];
36+
if (onceEvent.hasOwnProperty(name)) {
37+
onceEvent[name].forEach(function (listener) {
38+
listener(data);
39+
});
40+
41+
delete onceEvent[name];
42+
}
43+
}
44+
}
45+
46+
class RTC_Websocket {
47+
private websocket: WebSocket;
48+
private reconnectionInterval: number = 1000;
49+
private connectionState: string = 'standby';
50+
private willReconnect: boolean = true;
51+
private event: RTC_Event;
52+
53+
private defaultAuthToken: string | null = null;
54+
private reconnectionTimeout: NodeJS.Timeout;
55+
56+
constructor(
57+
private wsUri: string,
58+
private options: any[] = []
59+
) {
60+
this.event = new RTC_Event();
61+
62+
// HANDLE MESSAGE/EVENT DISPATCH WHEN DOM FINISHED LOADING
63+
this.onReady(() => {
64+
// Inspect messages and dispatch event
65+
this.onMessage((payload) => {
66+
if (payload.event) {
67+
// Dispatch unfiltered event events
68+
this.event.dispatch('event', [payload]);
69+
70+
// Dispatch filtered event event
71+
this.event.dispatch('event.' + payload.event, [payload]);
72+
}
73+
});
74+
});
75+
}
76+
77+
78+
/**
79+
* Check if connection is opened
80+
* @returns {boolean}
81+
*/
82+
isOpened(): boolean {
83+
return 'open' === this.connectionState;
84+
};
85+
86+
/**
87+
* Gets server connection state
88+
* @returns {string}
89+
*/
90+
getState(): string {
91+
return this.connectionState;
92+
};
93+
94+
/**
95+
* Get browser implementation of WebSocket object
96+
* @return {WebSocket}
97+
*/
98+
getWebSocket(): WebSocket {
99+
return this.websocket
100+
};
101+
102+
/**
103+
* This event fires when a connection is opened/created
104+
* @param listener
105+
*/
106+
onOpen(listener): RTC_Websocket {
107+
this.event.on('open', listener);
108+
return this;
109+
};
110+
111+
/**
112+
* This event fires when message is received
113+
* @param listener
114+
*/
115+
onMessage(listener): RTC_Websocket {
116+
this.event.on('message', (payload: any) => {
117+
if ('string' === typeof payload.data) {
118+
listener(JSON.parse(payload.data), payload)
119+
} else {
120+
listener(payload, payload);
121+
}
122+
});
123+
124+
return this;
125+
};
126+
127+
/**
128+
* Listens to filtered websocket event message
129+
*
130+
* @param event {string}
131+
* @param listener {callback}
132+
*/
133+
onEvent(event: string, listener: CallableFunction): RTC_Websocket {
134+
this.event.on('event.' + event, listener);
135+
return this;
136+
};
137+
138+
/**
139+
* Listens to RTC socket event
140+
*
141+
* @param listener
142+
*/
143+
onAnyEvent(listener: CallableFunction): RTC_Websocket {
144+
this.event.on('event', listener);
145+
return this;
146+
};
147+
148+
/**
149+
* This event fires when this connection is closed
150+
*
151+
* @param listener
152+
*/
153+
onClose(listener: CallableFunction): RTC_Websocket {
154+
this.event.on('close', listener);
155+
return this;
156+
};
157+
158+
/**
159+
* This event fires when client is disconnecting this connection
160+
*
161+
* @param listener
162+
*/
163+
onDisconnect(listener: CallableFunction): RTC_Websocket {
164+
this.event.on('custom.disconnect', listener);
165+
return this;
166+
};
167+
168+
/**
169+
* This event fires when an error occurred
170+
* @param listener
171+
*/
172+
onError(listener: CallableFunction): RTC_Websocket {
173+
this.event.on('error', listener);
174+
return this;
175+
};
176+
177+
/**
178+
* This event fires when this connection is in connecting state
179+
* @param listener
180+
*/
181+
onConnecting(listener: CallableFunction): RTC_Websocket {
182+
this.event.on('connecting', listener);
183+
return this;
184+
};
185+
186+
/**
187+
* This event fires when this reconnection is in connecting state
188+
* @param listener
189+
*/
190+
onReconnecting(listener: CallableFunction): RTC_Websocket {
191+
this.event.on('reconnecting', listener);
192+
return this;
193+
};
194+
195+
/**
196+
* This event fires when this reconnection has been reconnected
197+
* @param listener
198+
*/
199+
onReconnect(listener: CallableFunction): RTC_Websocket {
200+
this.event.on('reconnect', listener);
201+
return this;
202+
};
203+
204+
205+
onReady(listener): void {
206+
window.addEventListener('DOMContentLoaded', listener);
207+
};
208+
209+
/**
210+
* Set reconnection interval
211+
* @param interval
212+
*/
213+
setReconnectionInterval(interval: number): RTC_Websocket {
214+
this.reconnectionInterval = interval;
215+
return this;
216+
};
217+
218+
/**
219+
* Set an authentication token that will be included in each outgoing message
220+
*
221+
* @param token {string} authentication token
222+
*/
223+
setAuthToken(token: string): RTC_Websocket {
224+
this.defaultAuthToken = token;
225+
return this;
226+
};
227+
228+
229+
/**
230+
* Manually reconnect this connection
231+
*/
232+
reconnect(): void {
233+
this.closeConnection(true);
234+
235+
if (this.reconnectionInterval) {
236+
this.reconnectionTimeout = setTimeout(
237+
() => this.createSocket(true),
238+
this.reconnectionInterval
239+
);
240+
}
241+
};
242+
243+
/**
244+
* Connect to websocket server
245+
*
246+
* @returns {RTC_Websocket}
247+
*/
248+
connect(): RTC_Websocket {
249+
// Create websocket connection
250+
this.createSocket();
251+
252+
return this;
253+
};
254+
255+
/**
256+
* Close this connection, the connection will not be reconnected.
257+
*/
258+
close() {
259+
this.willReconnect = false;
260+
this.closeConnection(false)
261+
clearTimeout(this.reconnectionTimeout);
262+
this.event.dispatch('custom.disconnect');
263+
};
264+
265+
266+
/**
267+
* Send message to websocket server
268+
* @param event {any} event name
269+
* @param message {array|object|int|float|string} message
270+
* @return Promise
271+
*/
272+
send(event: string, message: {} = {}): Promise<any> {
273+
event = JSON.stringify({
274+
event: event,
275+
message: message,
276+
time: new Date().getTime(),
277+
token: this.defaultAuthToken
278+
});
279+
280+
//Send message
281+
return new Promise((resolve, reject) => {
282+
//Only send message when client is connected
283+
if (this.isOpened()) {
284+
try {
285+
this.websocket.send(event);
286+
resolve(this);
287+
} catch (error) {
288+
reject(error);
289+
}
290+
291+
//Send message when connection is recovered
292+
} else {
293+
this.log('Your message will be sent when server connection is recovered!');
294+
this.event.once('open', () => {
295+
try {
296+
this.websocket.send(event);
297+
resolve(this);
298+
} catch (error) {
299+
reject(error);
300+
}
301+
});
302+
}
303+
})
304+
};
305+
306+
private log(message: any): void {
307+
console.log(message);
308+
};
309+
310+
private changeState(stateName: string, event: any[]): void {
311+
this.connectionState = stateName;
312+
313+
if ('close' === stateName && this.willReconnect) {
314+
this.reconnect();
315+
}
316+
317+
this.event.dispatch(stateName, [event]);
318+
};
319+
320+
private closeConnection(reconnect: boolean = false): void {
321+
if (reconnect) {
322+
this.willReconnect = true;
323+
this.connectionState = 'internal_reconnection';
324+
}
325+
326+
this.websocket.close();
327+
};
328+
329+
private createSocket(isReconnecting: boolean = false): void {
330+
if (true === isReconnecting) {
331+
this.connectionState = 'reconnecting';
332+
this.event.dispatch('reconnecting');
333+
} else {
334+
this.connectionState = 'connecting';
335+
this.event.dispatch('connecting');
336+
337+
}
338+
339+
if (this.wsUri.indexOf('ws://') === -1 && this.wsUri.indexOf('wss://') === -1) {
340+
this.wsUri = 'ws://' + window.location.host + this.wsUri;
341+
}
342+
343+
this.websocket = new WebSocket(this.wsUri, []);
344+
345+
this.websocket.addEventListener('open', (...args) => {
346+
if ('reconnecting' === this.connectionState) {
347+
this.event.dispatch('reconnect');
348+
}
349+
350+
this.changeState('open', args);
351+
});
352+
353+
this.websocket.addEventListener('message', (...args) => {
354+
this.event.dispatch('message', args);
355+
});
356+
357+
this.websocket.addEventListener('close', (...args) => {
358+
this.changeState('close', args);
359+
});
360+
361+
this.websocket.addEventListener('error', (...args) => {
362+
this.changeState('error', args);
363+
});
364+
}
365+
}

0 commit comments

Comments
 (0)