socket.io-client-v2 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +67 -0
- package/dist/socket.io.dev.js +6667 -0
- package/dist/socket.io.dev.js.map +1 -0
- package/dist/socket.io.js +9 -0
- package/dist/socket.io.js.map +1 -0
- package/dist/socket.io.slim.dev.js +5901 -0
- package/dist/socket.io.slim.dev.js.map +1 -0
- package/dist/socket.io.slim.js +9 -0
- package/dist/socket.io.slim.js.map +1 -0
- package/lib/index.js +94 -0
- package/lib/manager.js +577 -0
- package/lib/on.js +24 -0
- package/lib/socket.js +438 -0
- package/lib/url.js +75 -0
- package/package.json +87 -0
package/lib/index.js
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* Module dependencies.
|
4
|
+
*/
|
5
|
+
|
6
|
+
var url = require('./url');
|
7
|
+
var parser = require('socket.io-parser');
|
8
|
+
var Manager = require('./manager');
|
9
|
+
var debug = require('debug')('socket.io-client');
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Module exports.
|
13
|
+
*/
|
14
|
+
|
15
|
+
module.exports = exports = lookup;
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Managers cache.
|
19
|
+
*/
|
20
|
+
|
21
|
+
var cache = exports.managers = {};
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Looks up an existing `Manager` for multiplexing.
|
25
|
+
* If the user summons:
|
26
|
+
*
|
27
|
+
* `io('http://localhost/a');`
|
28
|
+
* `io('http://localhost/b');`
|
29
|
+
*
|
30
|
+
* We reuse the existing instance based on same scheme/port/host,
|
31
|
+
* and we initialize sockets for each namespace.
|
32
|
+
*
|
33
|
+
* @api public
|
34
|
+
*/
|
35
|
+
|
36
|
+
function lookup (uri, opts) {
|
37
|
+
if (typeof uri === 'object') {
|
38
|
+
opts = uri;
|
39
|
+
uri = undefined;
|
40
|
+
}
|
41
|
+
|
42
|
+
opts = opts || {};
|
43
|
+
|
44
|
+
var parsed = url(uri);
|
45
|
+
var source = parsed.source;
|
46
|
+
var id = parsed.id;
|
47
|
+
var path = parsed.path;
|
48
|
+
var sameNamespace = cache[id] && path in cache[id].nsps;
|
49
|
+
var newConnection = opts.forceNew || opts['force new connection'] ||
|
50
|
+
false === opts.multiplex || sameNamespace;
|
51
|
+
|
52
|
+
var io;
|
53
|
+
|
54
|
+
if (newConnection) {
|
55
|
+
debug('ignoring socket cache for %s', source);
|
56
|
+
io = Manager(source, opts);
|
57
|
+
} else {
|
58
|
+
if (!cache[id]) {
|
59
|
+
debug('new io instance for %s', source);
|
60
|
+
cache[id] = Manager(source, opts);
|
61
|
+
}
|
62
|
+
io = cache[id];
|
63
|
+
}
|
64
|
+
if (parsed.query && !opts.query) {
|
65
|
+
opts.query = parsed.query;
|
66
|
+
}
|
67
|
+
return io.socket(parsed.path, opts);
|
68
|
+
}
|
69
|
+
|
70
|
+
/**
|
71
|
+
* Protocol version.
|
72
|
+
*
|
73
|
+
* @api public
|
74
|
+
*/
|
75
|
+
|
76
|
+
exports.protocol = parser.protocol;
|
77
|
+
|
78
|
+
/**
|
79
|
+
* `connect`.
|
80
|
+
*
|
81
|
+
* @param {String} uri
|
82
|
+
* @api public
|
83
|
+
*/
|
84
|
+
|
85
|
+
exports.connect = lookup;
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Expose constructors for standalone build.
|
89
|
+
*
|
90
|
+
* @api public
|
91
|
+
*/
|
92
|
+
|
93
|
+
exports.Manager = require('./manager');
|
94
|
+
exports.Socket = require('./socket');
|
package/lib/manager.js
ADDED
@@ -0,0 +1,577 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* Module dependencies.
|
4
|
+
*/
|
5
|
+
|
6
|
+
var eio = require('engine.io-client');
|
7
|
+
var Socket = require('./socket');
|
8
|
+
var Emitter = require('component-emitter');
|
9
|
+
var parser = require('socket.io-parser');
|
10
|
+
var on = require('./on');
|
11
|
+
var bind = require('component-bind');
|
12
|
+
var debug = require('debug')('socket.io-client:manager');
|
13
|
+
var indexOf = require('indexof');
|
14
|
+
var Backoff = require('backo2');
|
15
|
+
|
16
|
+
/**
|
17
|
+
* IE6+ hasOwnProperty
|
18
|
+
*/
|
19
|
+
|
20
|
+
var has = Object.prototype.hasOwnProperty;
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Module exports
|
24
|
+
*/
|
25
|
+
|
26
|
+
module.exports = Manager;
|
27
|
+
|
28
|
+
/**
|
29
|
+
* `Manager` constructor.
|
30
|
+
*
|
31
|
+
* @param {String} engine instance or engine uri/opts
|
32
|
+
* @param {Object} options
|
33
|
+
* @api public
|
34
|
+
*/
|
35
|
+
|
36
|
+
function Manager (uri, opts) {
|
37
|
+
if (!(this instanceof Manager)) return new Manager(uri, opts);
|
38
|
+
if (uri && ('object' === typeof uri)) {
|
39
|
+
opts = uri;
|
40
|
+
uri = undefined;
|
41
|
+
}
|
42
|
+
opts = opts || {};
|
43
|
+
|
44
|
+
opts.path = opts.path || '/socket.io';
|
45
|
+
this.nsps = {};
|
46
|
+
this.subs = [];
|
47
|
+
this.opts = opts;
|
48
|
+
this.reconnection(opts.reconnection !== false);
|
49
|
+
this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
|
50
|
+
this.reconnectionDelay(opts.reconnectionDelay || 1000);
|
51
|
+
this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
|
52
|
+
this.randomizationFactor(opts.randomizationFactor || 0.5);
|
53
|
+
this.backoff = new Backoff({
|
54
|
+
min: this.reconnectionDelay(),
|
55
|
+
max: this.reconnectionDelayMax(),
|
56
|
+
jitter: this.randomizationFactor()
|
57
|
+
});
|
58
|
+
this.timeout(null == opts.timeout ? 20000 : opts.timeout);
|
59
|
+
this.readyState = 'closed';
|
60
|
+
this.uri = uri;
|
61
|
+
this.connecting = [];
|
62
|
+
this.lastPing = null;
|
63
|
+
this.encoding = false;
|
64
|
+
this.packetBuffer = [];
|
65
|
+
var _parser = opts.parser || parser;
|
66
|
+
this.encoder = new _parser.Encoder();
|
67
|
+
this.decoder = new _parser.Decoder();
|
68
|
+
this.autoConnect = opts.autoConnect !== false;
|
69
|
+
if (this.autoConnect) this.open();
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Propagate given event to sockets and emit on `this`
|
74
|
+
*
|
75
|
+
* @api private
|
76
|
+
*/
|
77
|
+
|
78
|
+
Manager.prototype.emitAll = function () {
|
79
|
+
this.emit.apply(this, arguments);
|
80
|
+
for (var nsp in this.nsps) {
|
81
|
+
if (has.call(this.nsps, nsp)) {
|
82
|
+
this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
};
|
86
|
+
|
87
|
+
/**
|
88
|
+
* Update `socket.id` of all sockets
|
89
|
+
*
|
90
|
+
* @api private
|
91
|
+
*/
|
92
|
+
|
93
|
+
Manager.prototype.updateSocketIds = function () {
|
94
|
+
for (var nsp in this.nsps) {
|
95
|
+
if (has.call(this.nsps, nsp)) {
|
96
|
+
this.nsps[nsp].id = this.generateId(nsp);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
};
|
100
|
+
|
101
|
+
/**
|
102
|
+
* generate `socket.id` for the given `nsp`
|
103
|
+
*
|
104
|
+
* @param {String} nsp
|
105
|
+
* @return {String}
|
106
|
+
* @api private
|
107
|
+
*/
|
108
|
+
|
109
|
+
Manager.prototype.generateId = function (nsp) {
|
110
|
+
return (nsp === '/' ? '' : (nsp + '#')) + this.engine.id;
|
111
|
+
};
|
112
|
+
|
113
|
+
/**
|
114
|
+
* Mix in `Emitter`.
|
115
|
+
*/
|
116
|
+
|
117
|
+
Emitter(Manager.prototype);
|
118
|
+
|
119
|
+
/**
|
120
|
+
* Sets the `reconnection` config.
|
121
|
+
*
|
122
|
+
* @param {Boolean} true/false if it should automatically reconnect
|
123
|
+
* @return {Manager} self or value
|
124
|
+
* @api public
|
125
|
+
*/
|
126
|
+
|
127
|
+
Manager.prototype.reconnection = function (v) {
|
128
|
+
if (!arguments.length) return this._reconnection;
|
129
|
+
this._reconnection = !!v;
|
130
|
+
return this;
|
131
|
+
};
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Sets the reconnection attempts config.
|
135
|
+
*
|
136
|
+
* @param {Number} max reconnection attempts before giving up
|
137
|
+
* @return {Manager} self or value
|
138
|
+
* @api public
|
139
|
+
*/
|
140
|
+
|
141
|
+
Manager.prototype.reconnectionAttempts = function (v) {
|
142
|
+
if (!arguments.length) return this._reconnectionAttempts;
|
143
|
+
this._reconnectionAttempts = v;
|
144
|
+
return this;
|
145
|
+
};
|
146
|
+
|
147
|
+
/**
|
148
|
+
* Sets the delay between reconnections.
|
149
|
+
*
|
150
|
+
* @param {Number} delay
|
151
|
+
* @return {Manager} self or value
|
152
|
+
* @api public
|
153
|
+
*/
|
154
|
+
|
155
|
+
Manager.prototype.reconnectionDelay = function (v) {
|
156
|
+
if (!arguments.length) return this._reconnectionDelay;
|
157
|
+
this._reconnectionDelay = v;
|
158
|
+
this.backoff && this.backoff.setMin(v);
|
159
|
+
return this;
|
160
|
+
};
|
161
|
+
|
162
|
+
Manager.prototype.randomizationFactor = function (v) {
|
163
|
+
if (!arguments.length) return this._randomizationFactor;
|
164
|
+
this._randomizationFactor = v;
|
165
|
+
this.backoff && this.backoff.setJitter(v);
|
166
|
+
return this;
|
167
|
+
};
|
168
|
+
|
169
|
+
/**
|
170
|
+
* Sets the maximum delay between reconnections.
|
171
|
+
*
|
172
|
+
* @param {Number} delay
|
173
|
+
* @return {Manager} self or value
|
174
|
+
* @api public
|
175
|
+
*/
|
176
|
+
|
177
|
+
Manager.prototype.reconnectionDelayMax = function (v) {
|
178
|
+
if (!arguments.length) return this._reconnectionDelayMax;
|
179
|
+
this._reconnectionDelayMax = v;
|
180
|
+
this.backoff && this.backoff.setMax(v);
|
181
|
+
return this;
|
182
|
+
};
|
183
|
+
|
184
|
+
/**
|
185
|
+
* Sets the connection timeout. `false` to disable
|
186
|
+
*
|
187
|
+
* @return {Manager} self or value
|
188
|
+
* @api public
|
189
|
+
*/
|
190
|
+
|
191
|
+
Manager.prototype.timeout = function (v) {
|
192
|
+
if (!arguments.length) return this._timeout;
|
193
|
+
this._timeout = v;
|
194
|
+
return this;
|
195
|
+
};
|
196
|
+
|
197
|
+
/**
|
198
|
+
* Starts trying to reconnect if reconnection is enabled and we have not
|
199
|
+
* started reconnecting yet
|
200
|
+
*
|
201
|
+
* @api private
|
202
|
+
*/
|
203
|
+
|
204
|
+
Manager.prototype.maybeReconnectOnOpen = function () {
|
205
|
+
// Only try to reconnect if it's the first time we're connecting
|
206
|
+
if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) {
|
207
|
+
// keeps reconnection from firing twice for the same reconnection loop
|
208
|
+
this.reconnect();
|
209
|
+
}
|
210
|
+
};
|
211
|
+
|
212
|
+
/**
|
213
|
+
* Sets the current transport `socket`.
|
214
|
+
*
|
215
|
+
* @param {Function} optional, callback
|
216
|
+
* @return {Manager} self
|
217
|
+
* @api public
|
218
|
+
*/
|
219
|
+
|
220
|
+
Manager.prototype.open =
|
221
|
+
Manager.prototype.connect = function (fn, opts) {
|
222
|
+
debug('readyState %s', this.readyState);
|
223
|
+
if (~this.readyState.indexOf('open')) return this;
|
224
|
+
|
225
|
+
debug('opening %s', this.uri);
|
226
|
+
this.engine = eio(this.uri, this.opts);
|
227
|
+
var socket = this.engine;
|
228
|
+
var self = this;
|
229
|
+
this.readyState = 'opening';
|
230
|
+
this.skipReconnect = false;
|
231
|
+
|
232
|
+
// emit `open`
|
233
|
+
var openSub = on(socket, 'open', function () {
|
234
|
+
self.onopen();
|
235
|
+
fn && fn();
|
236
|
+
});
|
237
|
+
|
238
|
+
// emit `connect_error`
|
239
|
+
var errorSub = on(socket, 'error', function (data) {
|
240
|
+
debug('connect_error');
|
241
|
+
self.cleanup();
|
242
|
+
self.readyState = 'closed';
|
243
|
+
self.emitAll('connect_error', data);
|
244
|
+
if (fn) {
|
245
|
+
var err = new Error('Connection error');
|
246
|
+
err.data = data;
|
247
|
+
fn(err);
|
248
|
+
} else {
|
249
|
+
// Only do this if there is no fn to handle the error
|
250
|
+
self.maybeReconnectOnOpen();
|
251
|
+
}
|
252
|
+
});
|
253
|
+
|
254
|
+
// emit `connect_timeout`
|
255
|
+
if (false !== this._timeout) {
|
256
|
+
var timeout = this._timeout;
|
257
|
+
debug('connect attempt will timeout after %d', timeout);
|
258
|
+
|
259
|
+
if (timeout === 0) {
|
260
|
+
openSub.destroy(); // prevents a race condition with the 'open' event
|
261
|
+
}
|
262
|
+
|
263
|
+
// set timer
|
264
|
+
var timer = setTimeout(function () {
|
265
|
+
debug('connect attempt timed out after %d', timeout);
|
266
|
+
openSub.destroy();
|
267
|
+
socket.close();
|
268
|
+
socket.emit('error', 'timeout');
|
269
|
+
self.emitAll('connect_timeout', timeout);
|
270
|
+
}, timeout);
|
271
|
+
|
272
|
+
this.subs.push({
|
273
|
+
destroy: function () {
|
274
|
+
clearTimeout(timer);
|
275
|
+
}
|
276
|
+
});
|
277
|
+
}
|
278
|
+
|
279
|
+
this.subs.push(openSub);
|
280
|
+
this.subs.push(errorSub);
|
281
|
+
|
282
|
+
return this;
|
283
|
+
};
|
284
|
+
|
285
|
+
/**
|
286
|
+
* Called upon transport open.
|
287
|
+
*
|
288
|
+
* @api private
|
289
|
+
*/
|
290
|
+
|
291
|
+
Manager.prototype.onopen = function () {
|
292
|
+
debug('open');
|
293
|
+
|
294
|
+
// clear old subs
|
295
|
+
this.cleanup();
|
296
|
+
|
297
|
+
// mark as open
|
298
|
+
this.readyState = 'open';
|
299
|
+
this.emit('open');
|
300
|
+
|
301
|
+
// add new subs
|
302
|
+
var socket = this.engine;
|
303
|
+
this.subs.push(on(socket, 'data', bind(this, 'ondata')));
|
304
|
+
this.subs.push(on(socket, 'ping', bind(this, 'onping')));
|
305
|
+
this.subs.push(on(socket, 'pong', bind(this, 'onpong')));
|
306
|
+
this.subs.push(on(socket, 'error', bind(this, 'onerror')));
|
307
|
+
this.subs.push(on(socket, 'close', bind(this, 'onclose')));
|
308
|
+
this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
|
309
|
+
};
|
310
|
+
|
311
|
+
/**
|
312
|
+
* Called upon a ping.
|
313
|
+
*
|
314
|
+
* @api private
|
315
|
+
*/
|
316
|
+
|
317
|
+
Manager.prototype.onping = function () {
|
318
|
+
this.lastPing = new Date();
|
319
|
+
this.emitAll('ping');
|
320
|
+
};
|
321
|
+
|
322
|
+
/**
|
323
|
+
* Called upon a packet.
|
324
|
+
*
|
325
|
+
* @api private
|
326
|
+
*/
|
327
|
+
|
328
|
+
Manager.prototype.onpong = function () {
|
329
|
+
this.emitAll('pong', new Date() - this.lastPing);
|
330
|
+
};
|
331
|
+
|
332
|
+
/**
|
333
|
+
* Called with data.
|
334
|
+
*
|
335
|
+
* @api private
|
336
|
+
*/
|
337
|
+
|
338
|
+
Manager.prototype.ondata = function (data) {
|
339
|
+
this.decoder.add(data);
|
340
|
+
};
|
341
|
+
|
342
|
+
/**
|
343
|
+
* Called when parser fully decodes a packet.
|
344
|
+
*
|
345
|
+
* @api private
|
346
|
+
*/
|
347
|
+
|
348
|
+
Manager.prototype.ondecoded = function (packet) {
|
349
|
+
this.emit('packet', packet);
|
350
|
+
};
|
351
|
+
|
352
|
+
/**
|
353
|
+
* Called upon socket error.
|
354
|
+
*
|
355
|
+
* @api private
|
356
|
+
*/
|
357
|
+
|
358
|
+
Manager.prototype.onerror = function (err) {
|
359
|
+
debug('error', err);
|
360
|
+
this.emitAll('error', err);
|
361
|
+
};
|
362
|
+
|
363
|
+
/**
|
364
|
+
* Creates a new socket for the given `nsp`.
|
365
|
+
*
|
366
|
+
* @return {Socket}
|
367
|
+
* @api public
|
368
|
+
*/
|
369
|
+
|
370
|
+
Manager.prototype.socket = function (nsp, opts) {
|
371
|
+
var socket = this.nsps[nsp];
|
372
|
+
if (!socket) {
|
373
|
+
socket = new Socket(this, nsp, opts);
|
374
|
+
this.nsps[nsp] = socket;
|
375
|
+
var self = this;
|
376
|
+
socket.on('connecting', onConnecting);
|
377
|
+
socket.on('connect', function () {
|
378
|
+
socket.id = self.generateId(nsp);
|
379
|
+
});
|
380
|
+
|
381
|
+
if (this.autoConnect) {
|
382
|
+
// manually call here since connecting event is fired before listening
|
383
|
+
onConnecting();
|
384
|
+
}
|
385
|
+
}
|
386
|
+
|
387
|
+
function onConnecting () {
|
388
|
+
if (!~indexOf(self.connecting, socket)) {
|
389
|
+
self.connecting.push(socket);
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
return socket;
|
394
|
+
};
|
395
|
+
|
396
|
+
/**
|
397
|
+
* Called upon a socket close.
|
398
|
+
*
|
399
|
+
* @param {Socket} socket
|
400
|
+
*/
|
401
|
+
|
402
|
+
Manager.prototype.destroy = function (socket) {
|
403
|
+
var index = indexOf(this.connecting, socket);
|
404
|
+
if (~index) this.connecting.splice(index, 1);
|
405
|
+
if (this.connecting.length) return;
|
406
|
+
|
407
|
+
this.close();
|
408
|
+
};
|
409
|
+
|
410
|
+
/**
|
411
|
+
* Writes a packet.
|
412
|
+
*
|
413
|
+
* @param {Object} packet
|
414
|
+
* @api private
|
415
|
+
*/
|
416
|
+
|
417
|
+
Manager.prototype.packet = function (packet) {
|
418
|
+
debug('writing packet %j', packet);
|
419
|
+
var self = this;
|
420
|
+
if (packet.query && packet.type === 0) packet.nsp += '?' + packet.query;
|
421
|
+
|
422
|
+
if (!self.encoding) {
|
423
|
+
// encode, then write to engine with result
|
424
|
+
self.encoding = true;
|
425
|
+
this.encoder.encode(packet, function (encodedPackets) {
|
426
|
+
for (var i = 0; i < encodedPackets.length; i++) {
|
427
|
+
self.engine.write(encodedPackets[i], packet.options);
|
428
|
+
}
|
429
|
+
self.encoding = false;
|
430
|
+
self.processPacketQueue();
|
431
|
+
});
|
432
|
+
} else { // add packet to the queue
|
433
|
+
self.packetBuffer.push(packet);
|
434
|
+
}
|
435
|
+
};
|
436
|
+
|
437
|
+
/**
|
438
|
+
* If packet buffer is non-empty, begins encoding the
|
439
|
+
* next packet in line.
|
440
|
+
*
|
441
|
+
* @api private
|
442
|
+
*/
|
443
|
+
|
444
|
+
Manager.prototype.processPacketQueue = function () {
|
445
|
+
if (this.packetBuffer.length > 0 && !this.encoding) {
|
446
|
+
var pack = this.packetBuffer.shift();
|
447
|
+
this.packet(pack);
|
448
|
+
}
|
449
|
+
};
|
450
|
+
|
451
|
+
/**
|
452
|
+
* Clean up transport subscriptions and packet buffer.
|
453
|
+
*
|
454
|
+
* @api private
|
455
|
+
*/
|
456
|
+
|
457
|
+
Manager.prototype.cleanup = function () {
|
458
|
+
debug('cleanup');
|
459
|
+
|
460
|
+
var subsLength = this.subs.length;
|
461
|
+
for (var i = 0; i < subsLength; i++) {
|
462
|
+
var sub = this.subs.shift();
|
463
|
+
sub.destroy();
|
464
|
+
}
|
465
|
+
|
466
|
+
this.packetBuffer = [];
|
467
|
+
this.encoding = false;
|
468
|
+
this.lastPing = null;
|
469
|
+
|
470
|
+
this.decoder.destroy();
|
471
|
+
};
|
472
|
+
|
473
|
+
/**
|
474
|
+
* Close the current socket.
|
475
|
+
*
|
476
|
+
* @api private
|
477
|
+
*/
|
478
|
+
|
479
|
+
Manager.prototype.close =
|
480
|
+
Manager.prototype.disconnect = function () {
|
481
|
+
debug('disconnect');
|
482
|
+
this.skipReconnect = true;
|
483
|
+
this.reconnecting = false;
|
484
|
+
if ('opening' === this.readyState) {
|
485
|
+
// `onclose` will not fire because
|
486
|
+
// an open event never happened
|
487
|
+
this.cleanup();
|
488
|
+
}
|
489
|
+
this.backoff.reset();
|
490
|
+
this.readyState = 'closed';
|
491
|
+
if (this.engine) this.engine.close();
|
492
|
+
};
|
493
|
+
|
494
|
+
/**
|
495
|
+
* Called upon engine close.
|
496
|
+
*
|
497
|
+
* @api private
|
498
|
+
*/
|
499
|
+
|
500
|
+
Manager.prototype.onclose = function (reason) {
|
501
|
+
debug('onclose');
|
502
|
+
|
503
|
+
this.cleanup();
|
504
|
+
this.backoff.reset();
|
505
|
+
this.readyState = 'closed';
|
506
|
+
this.emit('close', reason);
|
507
|
+
|
508
|
+
if (this._reconnection && !this.skipReconnect) {
|
509
|
+
this.reconnect();
|
510
|
+
}
|
511
|
+
};
|
512
|
+
|
513
|
+
/**
|
514
|
+
* Attempt a reconnection.
|
515
|
+
*
|
516
|
+
* @api private
|
517
|
+
*/
|
518
|
+
|
519
|
+
Manager.prototype.reconnect = function () {
|
520
|
+
if (this.reconnecting || this.skipReconnect) return this;
|
521
|
+
|
522
|
+
var self = this;
|
523
|
+
|
524
|
+
if (this.backoff.attempts >= this._reconnectionAttempts) {
|
525
|
+
debug('reconnect failed');
|
526
|
+
this.backoff.reset();
|
527
|
+
this.emitAll('reconnect_failed');
|
528
|
+
this.reconnecting = false;
|
529
|
+
} else {
|
530
|
+
var delay = this.backoff.duration();
|
531
|
+
debug('will wait %dms before reconnect attempt', delay);
|
532
|
+
|
533
|
+
this.reconnecting = true;
|
534
|
+
var timer = setTimeout(function () {
|
535
|
+
if (self.skipReconnect) return;
|
536
|
+
|
537
|
+
debug('attempting reconnect');
|
538
|
+
self.emitAll('reconnect_attempt', self.backoff.attempts);
|
539
|
+
self.emitAll('reconnecting', self.backoff.attempts);
|
540
|
+
|
541
|
+
// check again for the case socket closed in above events
|
542
|
+
if (self.skipReconnect) return;
|
543
|
+
|
544
|
+
self.open(function (err) {
|
545
|
+
if (err) {
|
546
|
+
debug('reconnect attempt error');
|
547
|
+
self.reconnecting = false;
|
548
|
+
self.reconnect();
|
549
|
+
self.emitAll('reconnect_error', err.data);
|
550
|
+
} else {
|
551
|
+
debug('reconnect success');
|
552
|
+
self.onreconnect();
|
553
|
+
}
|
554
|
+
});
|
555
|
+
}, delay);
|
556
|
+
|
557
|
+
this.subs.push({
|
558
|
+
destroy: function () {
|
559
|
+
clearTimeout(timer);
|
560
|
+
}
|
561
|
+
});
|
562
|
+
}
|
563
|
+
};
|
564
|
+
|
565
|
+
/**
|
566
|
+
* Called upon successful reconnect.
|
567
|
+
*
|
568
|
+
* @api private
|
569
|
+
*/
|
570
|
+
|
571
|
+
Manager.prototype.onreconnect = function () {
|
572
|
+
var attempt = this.backoff.attempts;
|
573
|
+
this.reconnecting = false;
|
574
|
+
this.backoff.reset();
|
575
|
+
this.updateSocketIds();
|
576
|
+
this.emitAll('reconnect', attempt);
|
577
|
+
};
|
package/lib/on.js
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
/**
|
3
|
+
* Module exports.
|
4
|
+
*/
|
5
|
+
|
6
|
+
module.exports = on;
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Helper for subscriptions.
|
10
|
+
*
|
11
|
+
* @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
|
12
|
+
* @param {String} event name
|
13
|
+
* @param {Function} callback
|
14
|
+
* @api public
|
15
|
+
*/
|
16
|
+
|
17
|
+
function on (obj, ev, fn) {
|
18
|
+
obj.on(ev, fn);
|
19
|
+
return {
|
20
|
+
destroy: function () {
|
21
|
+
obj.removeListener(ev, fn);
|
22
|
+
}
|
23
|
+
};
|
24
|
+
}
|