resources/plezi_client.js in plezi-0.12.18 vs resources/plezi_client.js in plezi-0.12.19

- old
+ new

@@ -1,112 +1,138 @@ // This is a commonly used structure for WebSocket messanging. +// The documentation is available on the www.plezi.io website: +// http://www.plezi.io/docs/websockets#websocket-json-auto-dispatch // -// To open a websocket connection to the current location -// (i.e, "https://example.com/path" => "wss://example.com/path"), use: +// Basics: +// To open a websocket connection to the current location: // // var client = new PleziClient() // // To open a connection to a different path for the original server (SSL will be preserved when in use), use: // // var client = new PleziClient(PleziClient.origin + "/path") // -// i.e., to open a connection to the root ("/"), use: -// -// var client = new PleziClient(PleziClient.origin + "/") -// -// To open a connection to a different URL or path, use: -// -// var client = new PleziClient("ws://full.url.com/path") -// // To automatically renew the connection when disconnections are reported by the browser, use: // -// client.reconnect = true -// client.reconnect_interval = 250 // sets how long to wait before reconnection attempts. default is 50 ms. +// client.autoreconnect = true +// client.reconnect_interval = 250 // sets how long to wait before reconnection attempts. default is 250 ms. // -// The automatic renew flag can be used when creating the client, using: +// To set up event handling, directly set an `<event name>` callback. i.e., for an event called `chat`: // -// var client = new PleziClient(PleziClient.origin + "/path", true) -// client.reconnect_interval = 250 // Or use the default 50 ms. +// client.chat = function(event) { "..." } // -// To set up event handling, directly set an `on<event name>` callback. i.e., for an event called `chat`: -// -// client.onchat = function(event) { "..." } -// // To sent / emit event in JSON format, use the `emit` method: // // client.emit({event: "chat", data: "the message"}) // -// To sent raw websocket data, use the `send` method. -// This might cause disconnetions if Plezi's controller uses `auto_dispatch`. -// i.e. sending a string: -// -// client.send("string") -// -// Manually closing the connection will prevent automatic reconnection: -// -// client.close() -// -function PleziClient(url, reconnect) { - this.connected = NaN; +function PleziClient(url, autoreconnect) { + // Set URL if(url) { this.url = url } else { this.url = PleziClient.origin + window.location.pathname } - - this.ws = new WebSocket(this.url); - this.ws.owner = this - this.reconnect = false; - this.reconnect_interval = 50 - if(reconnect) {this.reconnect = true;} - this.ws.onopen = function(e) { - this.owner.connected = true; - if (this.owner.onopen) { this.owner.onopen(e) } + // Connect Websocket + this.reconnect(); + // auto-reconnection + this.autoreconnect = false; + this.reconnect_interval = 200 + // the timeout for a message ack receipt + this.emit_timeout = false + // Set the autoreconnect property + if(autoreconnect) {this.autoreconnect = true;} +} +// The Websocket onopen callback +PleziClient.prototype.___on_open = function(e) { + this.owner.connected = true; + if (this.owner.onopen) { this.owner.onopen(e) } +} +// The Websocket onclose callback +PleziClient.prototype.___on_close = function(e) { + this.owner.connected = false; + if (this.owner.onclose) { this.owner.onclose(e) } + if(this.owner.autoreconnect) { + setTimeout( function(obj) { + obj.reconnect(); + }, this.owner.reconnect_interval, this.owner); } - this.ws.onclose = function(e) { - this.connected = false; - if (this.owner.onclose) { this.owner.onclose(e) } - if(this.owner.reconnect) { - setTimeout( function(obj) { - obj.connected = NaN; - obj.ws = new Websocket(obj.url); - obj.ws.owner = obj - }, this.reconnect_interval, this.owner); - } - } - this.ws.onerror = function(e) { if (this.owner.onerror) {this.owner.onerror(e)} } - this.ws.onmessage = this.___on_message } - +// The Websocket onerror callback +PleziClient.prototype.___on_error = function(e) { + if (this.owner.onerror) {this.owner.onerror(e)} +} +// The Websocket onmessage callback PleziClient.prototype.___on_message = function(e) { try { var msg = JSON.parse(e.data); - if ( (msg.event) && (this.owner['on' + msg.event])) { + if ( msg.event == '_ack_') { clearTimeout(msg._EID_) } + if ( (msg.event) && (this.owner[msg.event])) { + this.owner[msg.event](msg); + } else if ( (msg.event) && (this.owner['on' + msg.event])) { + console.warn('PleziClient: use a callback called "' + msg.event + + '" instead of of "on' + msg.event + '"'); this.owner['on' + msg.event](msg); } else { - if (this.owner['unknown']) {this.owner['unknown'](msg)}; + if (this.owner['unknown'] && (msg.event != '_ack_') ) {this.owner['unknown'](msg)}; } } catch(err) { - console.error(err) + console.error("PleziClient experienced an error while responding to the following onmessage event", + err, e) } } +// Sets a timeout for the websocket message +PleziClient.prototype.___set_failed_timeout = function(event, callback, timeout) { + if(event._EID_) {return event;}; + if(!timeout) { timeout = this.emit_timeout; }; + if(!callback) { callback = this.___on_timeout; }; + if(!timeout) { return event; }; + event._EID_ = setTimeout(callback, timeout, event, this); + return event; +} +// Removes the _client_ property from the event and calls +// the ontimeout callback within the correct scope +PleziClient.prototype.___on_timeout = function(event, client) { + client.ontimeout(event) +} +// The timeout callback +PleziClient.prototype.ontimeout = function(event) { + console.warn("Timeout reached - it's assumed the connection was lost " + + "and the following event was ignored by the server:", event); + console.log(this); +} +PleziClient.prototype.reconnect = function() { + this.connected = NaN; + this.ws = new WebSocket(this.url); + // lets us access the client from the callbacks + this.ws.owner = this + // The Websocket onopen callback + this.ws.on_open = this.___on_open + // The Websocket onclose callback + this.ws.onclose = this.___on_close + // The Websocket onerror callback + this.ws.onerror = this.___on_error + // The Websocket onmessage callback + this.ws.onmessage = this.___on_message +} + PleziClient.prototype.close = function() { - this.reconnect = false; + this.autoreconnect = false; this.ws.close(); } PleziClient.origin = (window.location.protocol.match(/https/) ? 'wws' : 'ws') + '://' + window.location.hostname + (window.location.port == '' ? '' : (':' + window.location.port) ); -PleziClient.prototype.send = function(data) { +PleziClient.prototype.sendraw = function(data) { if (this.ws.readyState != 1) { return false; } this.ws.send(data); if (this.ws.readyState != 1) { return false; } return true } -PleziClient.prototype.emit = function(data) { - return this.send( JSON.stringify(data) ); +PleziClient.prototype.emit = function(event, callback, timeout) { + this.___set_failed_timeout(event, callback, timeout) + return this.sendraw( JSON.stringify(event) ); } PleziClient.prototype.readyState = function() { return this.ws.readyState; }