main/view/lib/ws-client-es6.js

212 lines
4.6 KiB
JavaScript

/* classe client WebSocket */
class WSClient{
/* (1) Constructor
*
* @server_url<String> The url of the desired server
* @channel_uri<String> The url of the desired channel
*
---------------------------------------------------------*/
constructor(server_url, channel_uri){
/* (1) Store & create data
---------------------------------------------------------*/
/* (1) Store the arguments */
this.server_url = server_url;
this.channel_uri = channel_uri;
/* (2) Initialise event data */
this.is_opened = false; // Set to TRUE when connection opened
this.pending = null; // Next message to send through connection
this.handler = []; // On reveice handlers
/* (3) Create the websocket connection */
this.ws = new WebSocket(this.server_url+'/'+channel_uri);
/* (2) Bind events
---------------------------------------------------------*/
/* (1) OPEN: when connection is established */
this.ws.onopen = this._onopen.bind(this);
/* (2) MESSAGE: when message received */
this.ws.onmessage = this._onmessage.bind(this);
/* (3) ERROR: when websocket error */
this.ws.onerror = this._onerror.bind(this);
/* (4) CLOSE: when websocket closes */
this.ws.onclose = this._onclose.bind(this);
}
/* (2) Binds a handle to the onReceive event (global only)
*
* @callback<Function> Callback function(message, error)
*
---------------------------------------------------------*/
listen(callback){
/* (1) Check @callback type (default value) */
if( !(callback instanceof Function) )
throw new Error('WSClient.bind(callback) expected argument *callback* to be a function');
/* (2) Store callback */
this.on_receive = callback;
return this;
}
/* (3) Sends a message through the socket
*
* @message<String> The data to send
* <Object> The data to send (will be serialized)
*
---------------------------------------------------------*/
send(message){
/* (1) Manage arguments
---------------------------------------------------------*/
/* (2) Check @message type */
if( typeof message != 'string' && typeof message != 'object' ){
this.on_receive(null, 'wrong message type');
return this;
}
/* (2) Stringify JSON if object */
if( typeof message == 'object' )
message = JSON.stringify(message);
/* (2) Send process
---------------------------------------------------------*/
/* (1) If not opened -> store message (will send when onopen()) */
if( !this.is_opened )
this.pending = message;
/* (2) If already opened -> send now */
else
this.ws.send(message);
return this;
}
/* (4) PRIVATE: Open handler
*
---------------------------------------------------------*/
_onopen(){
/* (1) Set @is_opened status variable */
this.is_opened = true;
/* (2) If message pending */
if( this.pending != null ){
this.ws.send(this.pending); // send message
this.pending = null; // reset message (optional)
}
}
/* (5) PRIVATE: Receive handler
*
---------------------------------------------------------*/
_onmessage(msg_event){
/* (1) If not trusted -> error */
if( !msg_event.isTrusted ){
this.on_receive(null, 'not trusted');
return;
}
/* (2) If wrong origin -> error */
if( msg_event.origin != this.server_url ){
this.on_receive(null, 'unknown origin');
return;
}
/* (3) Try to JSON parse */
var parsedMsg = null;
try{
parsedMsg = JSON.parse(msg_event.data);
}catch(e){
this.on_receive(null, 'JSON error');
return;
}
/* (4) If all right -> success */
this.on_receive(parsedMsg, null);
}
/* (6) PRIVATE: Error handler
*
---------------------------------------------------------*/
_onerror(){
/* (1) Remove other handlers (only 1 error) */
this.ws.onmessage = null;
this.ws.onclose = null;
/* (2) Send error */
this.on_receive(null, 'websocket error');
}
/* (7) PRIVATE: Close handler
*
---------------------------------------------------------*/
_onclose(){
/* (1) Remove onmessage (not to catch messages) */
this.ws.onmessage = null;
/* (2) Send end */
this.on_receive(null, 'websocket closed');
}
}
class WSClientBuilder{
/* (1) Constructor
*
* @server_url<String> The url of the desired server
*
---------------------------------------------------------*/
constructor(server_url){
/* (1) Store the server url */
this.server_url = server_url;
}
/* (2) Builds a WSClient with desired channel
*
* @channel_uri<String> The uri of the desired channel
*
---------------------------------------------------------*/
channel(channel_uri=''){
return new WSClient(this.server_url, channel_uri);
}
}
export{ WSClient, WSClientBuilder }