Skip to content

Commit 592c441

Browse files
committed
Merge pull request #26 from drewnoakes/master
API compatibility and documentation
2 parents 23d2fbc + 98dfbde commit 592c441

File tree

2 files changed

+204
-33
lines changed

2 files changed

+204
-33
lines changed

reconnecting-websocket.js

Lines changed: 91 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
/**
2424
* This behaves like a WebSocket in every way, except if it fails to connect,
25-
* or it gets disconnected, it will repeatedly poll until it succesfully connects
25+
* or it gets disconnected, it will repeatedly poll until it successfully connects
2626
* again.
2727
*
2828
* It is API compatible, so when you have:
@@ -42,7 +42,11 @@
4242
* onmessage
4343
* etc...
4444
*
45-
* It is API compatible with the standard WebSocket API.
45+
* It is API compatible with the standard WebSocket API, apart from the following members:
46+
*
47+
* - `bufferedAmount`
48+
* - `extensions`
49+
* - `binaryType`
4650
*
4751
* Latest version: https://github.com/joewalnes/reconnecting-websocket/
4852
* - Joe Walnes
@@ -58,46 +62,65 @@
5862
})(this, function () {
5963

6064
function ReconnectingWebSocket(url, protocols) {
61-
protocols = protocols || [];
62-
6365
// These can be altered by calling code.
66+
67+
/** Whether this instance should log debug messages. */
6468
this.debug = false;
69+
/** The number of milliseconds to delay before attempting to reconnect. */
6570
this.reconnectInterval = 1000;
71+
/** The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. */
6672
this.reconnectDecay = 1.5;
73+
/** The number of attempted reconnects since starting, or the last successful connection. */
6774
this.reconnectAttempts = 0;
75+
/** The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. */
6876
this.timeoutInterval = 2000;
6977

78+
// These should be treated as read-only properties
79+
80+
/** The URL as resolved by the constructor. This is always an absolute URL. Read only. */
81+
this.url = url;
82+
/**
83+
* The current state of the connection.
84+
* Can be one of: WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED
85+
* Read only.
86+
*/
87+
this.readyState = WebSocket.CONNECTING;
88+
/**
89+
* A string indicating the name of the sub-protocol the server selected; this will be one of
90+
* the strings specified in the protocols parameter when creating the WebSocket object.
91+
* Read only.
92+
*/
93+
this.protocol = null;
94+
95+
// Private state variables
96+
7097
var self = this;
7198
var ws;
7299
var forcedClose = false;
73100
var timedOut = false;
74-
75-
this.url = url;
76-
this.protocols = protocols;
77-
this.readyState = WebSocket.CONNECTING;
78-
this.URL = url; // Public API
101+
var eventTarget = document.createElement('div');
79102

80-
this.onopen = function(event) {
81-
};
103+
// Wire up "on*" properties as event handlers
82104

83-
this.onclose = function(event) {
84-
};
105+
eventTarget.addEventListener('open', function(event) { self.onopen(event); });
106+
eventTarget.addEventListener('close', function(event) { self.onclose(event); });
107+
eventTarget.addEventListener('connecting', function(event) { self.onconnecting(event); });
108+
eventTarget.addEventListener('message', function(event) { self.onmessage(event); });
109+
eventTarget.addEventListener('error', function(event) { self.onerror(event); });
85110

86-
this.onconnecting = function(event) {
87-
};
111+
// Expose the API required by EventTarget
88112

89-
this.onmessage = function(event) {
90-
};
91-
92-
this.onerror = function(event) {
93-
};
113+
this.addEventListener = eventTarget.addEventListener.bind(eventTarget);
114+
this.removeEventListener = eventTarget.removeEventListener.bind(eventTarget);
115+
this.dispatchEvent = eventTarget.dispatchEvent.bind(eventTarget);
94116

95117
function connect(reconnectAttempt) {
96-
ws = new WebSocket(url, protocols);
97-
98-
if(!reconnectAttempt)
99-
self.onconnecting();
100-
118+
ws = new WebSocket(url, protocols || []);
119+
120+
if (!reconnectAttempt) {
121+
eventTarget.dispatchEvent(new Event('connecting'));
122+
}
123+
101124
if (self.debug || ReconnectingWebSocket.debugAll) {
102125
console.debug('ReconnectingWebSocket', 'attempt-connect', url);
103126
}
@@ -117,10 +140,13 @@
117140
if (self.debug || ReconnectingWebSocket.debugAll) {
118141
console.debug('ReconnectingWebSocket', 'onopen', url);
119142
}
143+
self.protocol = ws.protocol;
120144
self.readyState = WebSocket.OPEN;
121-
reconnectAttempt = false;
122145
self.reconnectAttempts = 0;
123-
self.onopen(event);
146+
var e = new Event('open');
147+
e.isReconnect = reconnectAttempt;
148+
reconnectAttempt = false;
149+
eventTarget.dispatchEvent(e);
124150
};
125151

126152
ws.onclose = function(event) {
@@ -129,14 +155,15 @@
129155
if (forcedClose) {
130156
self.readyState = WebSocket.CLOSED;
131157
self.onclose(event);
158+
eventTarget.dispatchEvent(new Event('close'));
132159
} else {
133160
self.readyState = WebSocket.CONNECTING;
134-
self.onconnecting();
161+
eventTarget.dispatchEvent(new Event('connecting'));
135162
if (!reconnectAttempt && !timedOut) {
136163
if (self.debug || ReconnectingWebSocket.debugAll) {
137164
console.debug('ReconnectingWebSocket', 'onclose', url);
138165
}
139-
self.onclose(event);
166+
eventTarget.dispatchEvent(new Event('close'));
140167
}
141168
setTimeout(function() {
142169
self.reconnectAttempts++;
@@ -148,17 +175,24 @@
148175
if (self.debug || ReconnectingWebSocket.debugAll) {
149176
console.debug('ReconnectingWebSocket', 'onmessage', url, event.data);
150177
}
151-
self.onmessage(event);
178+
var e = new Event('message');
179+
e.data = event.data;
180+
eventTarget.dispatchEvent(e);
152181
};
153182
ws.onerror = function(event) {
154183
if (self.debug || ReconnectingWebSocket.debugAll) {
155184
console.debug('ReconnectingWebSocket', 'onerror', url, event);
156185
}
157-
self.onerror(event);
186+
eventTarget.dispatchEvent(new Event('event'));
158187
};
159188
}
160189
connect(false);
161190

191+
/**
192+
* Transmits data to the server over the WebSocket connection.
193+
*
194+
* @param data a text string, ArrayBuffer or Blob to send to the server.
195+
*/
162196
this.send = function(data) {
163197
if (ws) {
164198
if (self.debug || ReconnectingWebSocket.debugAll) {
@@ -170,10 +204,14 @@
170204
}
171205
};
172206

173-
this.close = function() {
207+
/**
208+
* Closes the WebSocket connection or connection attempt, if any.
209+
* If the connection is already CLOSED, this method does nothing.
210+
*/
211+
this.close = function(code, reason) {
174212
forcedClose = true;
175213
if (ws) {
176-
ws.close();
214+
ws.close(code, reason);
177215
}
178216
};
179217

@@ -189,9 +227,29 @@
189227
}
190228

191229
/**
230+
* An event listener to be called when the WebSocket connection's readyState changes to OPEN;
231+
* this indicates that the connection is ready to send and receive data.
232+
*/
233+
ReconnectingWebSocket.prototype.onopen = function(event) {};
234+
/** An event listener to be called when the WebSocket connection's readyState changes to CLOSED. */
235+
ReconnectingWebSocket.prototype.onclose = function(event) {};
236+
/** An event listener to be called when a connection begins being attempted. */
237+
ReconnectingWebSocket.prototype.onconnecting = function(event) {};
238+
/** An event listener to be called when a message is received from the server. */
239+
ReconnectingWebSocket.prototype.onmessage = function(event) {};
240+
/** An event listener to be called when an error occurs. */
241+
ReconnectingWebSocket.prototype.onerror = function(event) {};
242+
243+
/**
244+
* Whether all instances of ReconnectingWebSocket should log debug messages.
192245
* Setting this to true is the equivalent of setting all instances of ReconnectingWebSocket.debug to true.
193246
*/
194247
ReconnectingWebSocket.debugAll = false;
195248

249+
ReconnectingWebSocket.CONNECTING = WebSocket.CONNECTING;
250+
ReconnectingWebSocket.OPEN = WebSocket.OPEN;
251+
ReconnectingWebSocket.CLOSING = WebSocket.CLOSING;
252+
ReconnectingWebSocket.CLOSED = WebSocket.CLOSED;
253+
196254
return ReconnectingWebSocket;
197255
});

reconnecting-websockets.d.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Type definitions for reconnecting-websocket
2+
// Project: https://github.com/joewalnes/reconnecting-websocket
3+
// Definitions by: Drew Noakes <https://drewnoakes.com>
4+
// Definitions: https://github.com/borisyankov/DefinitelyTyped
5+
6+
interface OpenEvent extends Event
7+
{
8+
/** If true, we have reconnected, otherwise this is the initial connection attempt. */
9+
isReconnect: boolean;
10+
}
11+
12+
/**
13+
* Behaves as a regular WebSocket class and adds logic for reconnecting when disconnected.
14+
*/
15+
declare class ReconnectingWebSocket
16+
{
17+
/** Whether all instances of ReconnectingWebSocket should log debug messages. */
18+
static debugAll: boolean;
19+
20+
/** Whether this instance should log debug messages. */
21+
public debug: boolean;
22+
23+
/** The number of milliseconds to delay before attempting to reconnect. */
24+
public reconnectInterval: number;
25+
26+
/** The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. */
27+
public reconnectDecay: number;
28+
29+
/** The number of attempted reconnects since starting, or the last successful connection. */
30+
public reconnectAttempts: number;
31+
32+
/** The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. */
33+
public timeoutInterval: number;
34+
35+
/** An event listener to be called when a connection begins being attempted. */
36+
onconnecting: (ev: Event) => any;
37+
38+
addEventListener(type: "connecting", listener: (ev: Event) => any, useCapture?: boolean): void;
39+
40+
/**
41+
* Additional public API method to refresh the connection if still open (close, re-open).
42+
* For example, if the app suspects bad data / missed heart beats, it can try to refresh.
43+
*/
44+
refresh(): void;
45+
46+
/////////////////////////////////////////////////////////////////////////////////////////////////////////
47+
48+
/** The URL as resolved by the constructor. This is always an absolute URL. Read only. */
49+
public url: string;
50+
51+
/**
52+
* A string indicating the name of the sub-protocol the server selected; this will be one of
53+
* the strings specified in the protocols parameter when creating the WebSocket object.
54+
* Read only.
55+
*/
56+
public protocol: string;
57+
58+
/**
59+
* The current state of the connection.
60+
* Can be one of: WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED
61+
* Read only.
62+
*/
63+
public readyState: number;
64+
65+
/**
66+
*
67+
* @param url the absolute URL of the service, eg: ws://host:port/path
68+
* @param protocols an optional array of protocol strings
69+
*/
70+
constructor(url: string, protocols?: string[]);
71+
72+
/**
73+
* An event listener to be called when the WebSocket connection's readyState changes to OPEN;
74+
* this indicates that the connection is ready to send and receive data.
75+
*/
76+
onopen: (ev: Event) => any;
77+
78+
/** An event listener to be called when a message is received from the server. */
79+
onmessage: (ev: any) => any;
80+
81+
/** An event listener to be called when the WebSocket connection's readyState changes to CLOSED. */
82+
onclose: (ev: CloseEvent) => any;
83+
84+
/** An event listener to be called when an error occurs. */
85+
onerror: (ev: ErrorEvent) => any;
86+
87+
addEventListener(type: "open", listener: (ev: Event) => any, useCapture?: boolean): void;
88+
addEventListener(type: "message", listener: (ev: any) => any, useCapture?: boolean): void;
89+
addEventListener(type: "close", listener: (ev: CloseEvent) => any, useCapture?: boolean): void;
90+
addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void;
91+
92+
addEventListener(type: string, listener: EventListener, useCapture?: boolean): void;
93+
removeEventListener(name: string, listener: (ev: Event) => any, useCapture?: boolean);
94+
dispatchEvent(event: Event);
95+
96+
/**
97+
* Transmits data to the server over the WebSocket connection.
98+
*
99+
* @param data a text string, ArrayBuffer or Blob to send to the server.
100+
*/
101+
send(data: any): void;
102+
103+
/**
104+
* Closes the WebSocket connection or connection attempt, if any.
105+
* If the connection is already CLOSED, this method does nothing.
106+
*/
107+
close(code?: number, reason?: string): void;
108+
109+
static CONNECTING: number;
110+
static OPEN: number;
111+
static CLOSING: number;
112+
static CLOSED: number;
113+
}

0 commit comments

Comments
 (0)