JavaXT
|
|
WebSocket Classif(!javaxt) var javaxt={}; if(!javaxt.dhtml) javaxt.dhtml={}; //****************************************************************************** //** WebSocket //*****************************************************************************/ /** * Used to communicate with a server using web sockets. Currently, this is a * read-only listener designed to get updates and status messages from the * server. The listener will automatically reconnect to the server if the * network connnection is interrupted. <pre> var ws = new javaxt.dhtml.WebSocket({ url: "/live/stats", onMessage: function(msg){ console.log(msg); } }); var logout = function(){ ws.stop(); //stop listening to events and disconnect from the server }; </pre> * ******************************************************************************/ javaxt.dhtml.WebSocket = function(config) { var me = this; var defaultConfig = { /** Relative path the to websocket endpoint (e.g. "/updates"). You do not * need to specify a full url with a "ws://" or "wss://" prefix. */ url: "", /** Interval used to check whether the websocket is still alive and send * ping messages. Value is in milliseconds. Default is 15000 (1.5 seconds). */ keepAlive: 15000, /** Message to send to the server. This message is periodically sent to * the server to test whether it is still alive. See keepAlive config. */ pingMessage: "", /** Max amount of time to wait for the websocket to reconnect with the * server after a disconnect. Value is in milliseconds. Default is * 300000 (5 minutes). */ timeout: 5*60*1000, /** Class used to debug the websocket. This config is not required to use * this class. Implementations must implement an append() method. */ debugr : { append: function(msg){ //console.log(msg); } } }; var url; var socket; var timer; var connectionSuccess = false; var connectionStartTime, connectionEndTime; //************************************************************************** //** init //************************************************************************** var init = function(){ //Clone the config so we don't modify the original config object var clone = {}; javaxt.dhtml.utils.merge(clone, config); //Merge clone with default config javaxt.dhtml.utils.merge(clone, defaultConfig); config = clone; //Update events handlers for (var key in config) { if (config.hasOwnProperty(key)){ if (typeof config[key] == "function") { if (me[key] && typeof me[key] == "function"){ me[key] = config[key]; } } } } //Set url to websocket endpoint var protocol = window.location.protocol.toLowerCase(); if (protocol.indexOf("https")===0) protocol = "wss"; else protocol = "ws"; url = protocol + '://' + window.location.host; if (config.url.indexOf("/")!==0) url += "/"; var path = config.url; if (path){ var idx = path.indexOf("//"); if (idx>=0){ path = path.substring(idx+2); idx = path.indexOf("/"); if (idx>-1) path = path.substring(idx+1); } url += path; } connect(); }; //************************************************************************** //** connect //************************************************************************** var connect = function(){ var connectionStatusTimer; var debugr = config.debugr; if (timer) clearInterval(timer); timer = setInterval(function() { if (socket){ if (socket.readyState === WebSocket.OPEN) { socket.send(config.pingMessage); } else if (socket.readyState === WebSocket.CLOSED){ connect(); } } }, config.keepAlive); socket = new WebSocket(url); socket.onopen = function(){ debugr.append("onopen"); //Update the connectionSuccess variable after a small delay. This //gives us a chance to see if the socket closes immediately after //open (see onclose) connectionStatusTimer = setTimeout(function(){ connectionSuccess = true; connectionStartTime = new Date().getTime(); connectionEndTime = 0; }, 500); me.onConnect(); }; //Handle messages sent by the server socket.onmessage = function(event) { connectionSuccess = true; var msg = event.data; debugr.append(msg); me.onMessage(msg); }; //Reconnect on disconnect socket.onclose = function(event){ debugr.append("onclose"); debugr.append(event.code + ": " + event.reason); //Record timestamp of the disconnect if (!connectionEndTime) connectionEndTime = new Date().getTime(); //Try to reconnect if (connectionSuccess){ //Reconnect! if ((new Date().getTime()-connectionEndTime)<config.timeout){ me.onDisconnect(); connect(); } else{ //Hang up... me.stop(); clearTimeout(connectionStatusTimer); me.onTimeout(); me.onDisconnect(); } } else{ //Websocket failed! debugr.append("Websocket failed"); socket = null; clearTimeout(timer); clearTimeout(connectionStatusTimer); me.onFailure(event.code, event.reason); me.onDisconnect(); } }; socket.onerror = function(){ debugr.append("error!"); }; }; //************************************************************************** //** onConnect //************************************************************************** /** Called whenever a websocket connection is established with the server. * Note that this event will be fired whenever a connection is dropped and * then restablished. */ this.onConnect = function(){}; //************************************************************************** //** onDisconnect //************************************************************************** /** Called whenever a websocket connection is closed or severed. */ this.onDisconnect = function(){}; //************************************************************************** //** onMessage //************************************************************************** /** Called whenever a message is recieved from the server. */ this.onMessage = function(msg){}; //************************************************************************** //** onFailure //************************************************************************** /** Called whenever there is a problem connecting or reconnecting to the * server. */ this.onFailure = function(code, reason){}; //************************************************************************** //** onTimeout //************************************************************************** /** Called when a websocket is disconnected from the server for an extended * period of time. See timeout config. */ this.onTimeout = function(){}; //************************************************************************** //** start //************************************************************************** /** Used to open a websocket connection to the server and start listening to * events. Note that the websocket listener is started automatically when * this class is first initialized. This method is only intended to be used * after calling stop(). */ this.start = function(){ if (socket) return; connect(); }; //************************************************************************** //** stop //************************************************************************** /** Used to stop listening to events and close the websocket */ this.stop = function(){ connectionSuccess = false; if (timer) clearInterval(timer); if (socket){ socket.close(); socket = null; } }; //************************************************************************** //** send //************************************************************************** /** Used to send a message to the server via the websocket. */ this.send = function(message){ if (socket){ if (socket.readyState === WebSocket.OPEN) { socket.send(message); } else if (socket.readyState === WebSocket.CLOSED){ //Maybe queue the messages and send on reconnect? } } }; init(); }; |