Last active
April 6, 2017 17:01
-
-
Save jhollinger/f5904f3ef144a75f688f to your computer and use it in GitHub Desktop.
ManagedWebSocket - WebSocket wrapper to handle auto reconnecting and event re-binding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ManagedWebSocket is a thin wrapper around WebSocket that handles automatic reconnecting and re-binding. | |
* If the server/network drops the connection, it will keep trying to reconnect. However, you may call | |
* "kill" to permanently disconnect on the client side. The native WebSocket object is available as "ws". | |
* | |
* Use "on" to bind to normal WebSocket events (open, message, error, close), and to the following custom events: | |
* - connecting: Fired when it is attempting to connect or reconnect. | |
* - drop: Fired when the connection has been dropped by the server or network. (fired before "close") | |
* - kill: Fired when you call "kill" on the MWS. (fired before "close") | |
* | |
* Options: | |
* wait: milliseconds to wait between re-connect attempts. (default 3000) | |
* | |
* Example: | |
* var mws = new ManagedWebSocket("ws://example.com/chat", {wait: 3000}); | |
* mws.on('connecting', function() { console.log('Connecting...') }. | |
* on('open', function() { console.log('Connected') }. | |
* on('message', function(data) { console.log('Received ' + data) }. | |
* on('drop', function(data) { console.log('Connection lost') }; | |
* mws.send(data); // Forwarded to mws.ws.send, which is the wrapped WebSocket object | |
*/ | |
function ManagedWebSocket(url, options) { | |
if ( !options ) options = {}; | |
this.url = url; | |
this.wait = options['wait'] || 3000; | |
this.state = ManagedWebSocket.PENDING; | |
this.events = {}; | |
this._connect(); | |
window.addEventListener('beforeunload', this.kill.bind(this)); | |
} | |
// Add an event handler | |
ManagedWebSocket.prototype.on = function(event, callback) { | |
if ( !this.events[event] ) this.events[event] = new Array(); | |
this.events[event].push(callback); | |
return this; | |
}; | |
// Send a message through the socket | |
ManagedWebSocket.prototype.send = function(data) { | |
return this.ws.send(data); | |
}; | |
// Close the socket without attempting to reconnect | |
ManagedWebSocket.prototype.kill = function() { | |
this.state = ManagedWebSocket.KILLED; | |
this.ws.close(); | |
}; | |
// Open a WebSocket connection | |
ManagedWebSocket.prototype._connect = function() { | |
if ( this.state == ManagedWebSocket.CONNECTED ) return; | |
if ( (this.state == ManagedWebSocket.PENDING || this.state == ManagedWebSocket.DISCONNECTED) ) this._fire('connecting'); | |
this.state = ManagedWebSocket.CONNECTING; | |
this.ws = new WebSocket(this.url); | |
var _this = this; | |
this.ws.addEventListener('open', function(e) { | |
_this.state = ManagedWebSocket.CONNECTED; | |
_this._fire('open', e); | |
}); | |
this.ws.addEventListener('message', function(data) { | |
_this._fire('message', data); | |
}); | |
this.ws.addEventListener('error', function(e) { | |
_this._fire('error', e); | |
}); | |
this.ws.addEventListener('close', function(e) { | |
var timeout; | |
if ( _this.state == ManagedWebSocket.KILLED ) { | |
_this._fire('kill'); | |
} | |
else if ( _this.state == ManagedWebSocket.CONNECTED ) { | |
_this._fire('drop'); | |
_this.state = ManagedWebSocket.DISCONNECTED; | |
timeout = 1000; | |
} | |
else { | |
timeout = _this.wait; | |
} | |
if ( timeout ) setTimeout(_this._connect.bind(_this), timeout); | |
_this._fire('close', e); | |
}); | |
} | |
// Fire event handlers of a particular type, and pass an optional argument | |
ManagedWebSocket.prototype._fire = function(name, arg) { | |
if ( this.events[name] ) { | |
for ( var i=0; i < this.events[name].length; i++ ) { | |
this.events[name][i](arg); | |
} | |
} | |
}; | |
ManagedWebSocket.PENDING = 0; | |
ManagedWebSocket.CONNECTING = 1; | |
ManagedWebSocket.CONNECTED = 2; | |
ManagedWebSocket.DISCONNECTED = 3; | |
ManagedWebSocket.KILLED = 4; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment