lib/ReconnectingWebSocket.js
function ReconnectingWebSocket (url, options) {
  var me = this;

  this.id = options && options.id || randomUUID();
  this.url = url + '/?id=' + this.id;

  this.socket = null;
  this.opened = false;
  this.closed = false;

  this.options = {
    reconnectTimeout: Infinity, // ms
    reconnectInterval: 5000     // ms
    //reconnectDecay: 2 // TODO: reconnect decay
  };

  // copy the options
  if (options) {
    if ('reconnectTimeout' in options)  this.options.reconnectTimeout = options.reconnectTimeout;
    if ('reconnectInterval' in options) this.options.reconnectInterval = options.reconnectInterval;
  }

  this.queue = [];

  this.attempts = 0;
  this.reconnectTimer = null;

  function connect() {
    me.socket = new WebSocket(me.url);

    me.socket.onmessage = function (event) {
      me.onmessage(event);
    };

    me.socket.onerror = function (error) {
      if (me.socket.readyState === WebSocket.OPEN) {
        me.onerror(error);
      }
      else {
        reconnect();
      }
    };

    me.socket.onopen = function (event) {
      // reset the number of connection attempts
      me.attempts = 0;

      // emit events
      if (!me.opened) {
        me.onopen(event);
        me.opened = true;
      }
      else {
        me.onreconnect(event);
      }

      // flush all messages in the queue (if any)
      //console.log('flush messages ' + me.queue);
      while (me.queue.length > 0) {
        var data = me.queue.shift();
        me.socket.send(data);
      }
    };

    me.socket.onclose = function (event) {
      if (me.closed) {
        me.onclose(event);
      }
      else {
        // start auto-reconnect attempts
        reconnect();
      }
    }
  }

  function reconnect() {
    // check whether already reconnecting
    if (me.reconnectTimer) {
      return;
    }

    me.attempts++;
    if (me.attempts < me.options.reconnectTimeout / me.options.reconnectInterval) {
      me.reconnectTimer = setTimeout(function () {
        me.reconnectTimer = null;
        connect();
      }, me.options.reconnectInterval);
    }
    else {
      // no luck, let's give up...
      me.close();
    }
  }

  connect();
}
function ReconnectingWebSocket (url, options) {
  var me = this;

  this.id = options && options.id || randomUUID();
  this.url = url + '/?id=' + this.id;

  this.socket = null;
  this.opened = false;
  this.closed = false;

  this.options = {
    reconnectTimeout: Infinity, // ms
    reconnectInterval: 5000     // ms
    //reconnectDecay: 2 // TODO: reconnect decay
  };

  // copy the options
  if (options) {
    if ('reconnectTimeout' in options)  this.options.reconnectTimeout = options.reconnectTimeout;
    if ('reconnectInterval' in options) this.options.reconnectInterval = options.reconnectInterval;
  }

  this.queue = [];

  this.attempts = 0;
  this.reconnectTimer = null;

  function connect() {
    me.socket = new WebSocket(me.url);

    me.socket.onmessage = function (event) {
      me.onmessage(event);
    };

    me.socket.onerror = function (error) {
      if (me.socket.readyState === WebSocket.OPEN) {
        me.onerror(error);
      }
      else {
        reconnect();
      }
    };

    me.socket.onopen = function (event) {
      // reset the number of connection attempts
      me.attempts = 0;

      // emit events
      if (!me.opened) {
        me.onopen(event);
        me.opened = true;
      }
      else {
        me.onreconnect(event);
      }

      // flush all messages in the queue (if any)
      //console.log('flush messages ' + me.queue);
      while (me.queue.length > 0) {
        var data = me.queue.shift();
        me.socket.send(data);
      }
    };

    me.socket.onclose = function (event) {
      if (me.closed) {
        me.onclose(event);
      }
      else {
        // start auto-reconnect attempts
        reconnect();
      }
    }
  }

  function reconnect() {
    // check whether already reconnecting
    if (me.reconnectTimer) {
      return;
    }

    me.attempts++;
    if (me.attempts < me.options.reconnectTimeout / me.options.reconnectInterval) {
      me.reconnectTimer = setTimeout(function () {
        me.reconnectTimer = null;
        connect();
      }, me.options.reconnectInterval);
    }
    else {
      // no luck, let's give up...
      me.close();
    }
  }

  connect();
}
function ReconnectingWebSocket ( url , options ) { var me = this ; this . id = options && options . id || randomUUID ( ) ; this . url = url + '/?id=' + this . id ; this . socket = null ; this . opened = false ; this . closed = false ; this . options = { reconnectTimeout : Infinity , // ms reconnectInterval : 5000 // ms //reconnectDecay: 2 // TODO: reconnect decay } ; // copy the options if ( options ) { if ( 'reconnectTimeout' in options ) this . options . reconnectTimeout = options . reconnectTimeout ; if ( 'reconnectInterval' in options ) this . options . reconnectInterval = options . reconnectInterval ; } this . queue = [ ] ; this . attempts = 0 ; this . reconnectTimer = null ; function connect ( ) { me . socket = new WebSocket ( me . url ) ; me . socket . onmessage = function ( event ) { me . onmessage ( event ) ; } ; me . socket . onerror = function ( error ) { if ( me . socket . readyState === WebSocket . OPEN ) { me . onerror ( error ) ; } else { reconnect ( ) ; } } ; me . socket . onopen = function ( event ) { // reset the number of connection attempts me . attempts = 0 ; // emit events if ( ! me . opened ) { me . onopen ( event ) ; me . opened = true ; } else { me . onreconnect ( event ) ; } // flush all messages in the queue (if any) //console.log('flush messages ' + me.queue); while ( me . queue . length > 0 ) { var data = me . queue . shift ( ) ; me . socket . send ( data ) ; } } ; me . socket . onclose = function ( event ) { if ( me . closed ) { me . onclose ( event ) ; } else { // start auto-reconnect attempts reconnect ( ) ; } } } function reconnect ( ) { // check whether already reconnecting if ( me . reconnectTimer ) { return ; } me . attempts ++ ; if ( me . attempts < me . options . reconnectTimeout / me . options . reconnectInterval ) { me . reconnectTimer = setTimeout ( function ( ) { me . reconnectTimer = null ; connect ( ) ; } , me . options . reconnectInterval ) ; } else { // no luck, let's give up... me . close ( ) ; } } connect ( ) ; }
An automatically reconnecting WebSocket connection
@param {string} url
@param {Object} options    Available options:
- id: number | string          An optional identifier for the server
to be able to identify clients.
After connection, the client will send
a message {method: 'greeting', id: id}
- reconnectInterval: number    Reconnect interval in milliseconds
- reconnectInterval: number    Reconnect interval in milliseconds
@constructor
An automatically reconnecting WebSocket connection