I've written a small npm module. It is my first module. I'm asking you to review several things:
- The code. I am rather starter, so any wise critic will be super.
- Any suggestions or ideas on the library.
About module
Module is made to provide more comfort in using websockets via node.js, to help in organizing websockets communication code.
The logic lies in the messaging object. The library mostly serves its states, types, names and callbacks.
After socket connected. The usage looks like this:
/* Front. Send socket event to server */
socket.get("greet-server");
/* Front. OR we set callback when send event*/
socket.get("greet-server", null, function(data) {
console.log(data);
});
Methods can be: get, put, post, delete, notify (Mostly, just separating logic). Notify is just an 'event', for any logic you need. For example, our greet-server is more like "notify" type event.
socket.notify("greet-server2");
/* Back. Set handler for event "greet-server" */
socket.get("greet-server", function(data, callback) {
console.log("Client greeted the server.");
if(data) console.log(data);
/* Set info for clients callback
As far as client has no callback this message wont be displayed */
callback(null, "Greet the client too");
});
socket.notify("greet-server2", function(data, callback){
console.log("Client notified server");
callback(null);
});
Server can also notify clients, but all together using method "notifyAll".
socket.notifyAll("get-new-info");
More info can be found here: Npm-module | Github
Below you'll find the main code.
Back-end, file "index.js"
"use strict";
/* Back-end part */
const ws = require('ws');
/*
Message structure (JSON.stringified):
id - identificator
type - method type (get, put, delete, post, notify)
name - event name
data - data object
error - null or error message
callback - true/false (to notify whether it's callback)
*/
var m = module.exports = {
handlers : {
get : {},
post : {},
put : {},
delete : {},
notify : {}
},
clients : {},
init : function(port, callback) {
let p = port || 8081;
m.server = new ws.Server({port: p});
m.server.on('connection', function(ws) {
callback(ws);
var id = Math.random();
m.clients[id] = ws;
ws.on('message', function(data) {
let msg = JSON.parse(data);
// Pass message to handle function
if( typeof m.handlers[msg.type] !== "undefined" &&
typeof m.handlers[msg.type][msg.name] !== "undefined" ) {
m.handle(msg.type, msg.name, msg.data, function(error, outerData) {
ws.send(JSON.stringify({
id : msg.id,
type : msg.type,
data : outerData,
name : msg.name,
error : error,
callback : true
}));
});
} else {
m.throwErr( ws, "Sorry, no back-end handler found.");
}
});
ws.on('close', function() {
delete m.clients[id];
});
});
},
handle : function(type, name, data, callback) {
m.handlers[type][name](data, callback);
},
get : function(name, callback) {
m.handlers.get[name] = callback;
},
post : function(name, callback) {
m.handlers.post[name] = callback;
},
put : function(name, callback) {
m.handlers.put[name] = callback;
},
delete : function(name, callback) {
m.handlers.delete[name] = callback;
},
notify : function(name, callback) {
m.handlers.notify[name] = callback;
},
notifyAll : function(name) {
for (var key in m.clients) {
m.clients[key].send(JSON.stringify({
id: 0,
type: "server-notify",
name: name,
data : null,
error: null,
callback: false
}));
}
},
remove : function(method, name) {
if( typeof m.handlers[method][name] !== 'undefined' )
delete m.handlers[method][name];
},
throwErr : function(ws, data, message) {
let msg = JSON.parse(data);
ws.send(JSON.stringify({
id: msg.id,
type: msg.type,
name: msg.name,
data : null,
error: message,
callback: false
}));
}
};
Front-end part, library - "lib/socket-event.js":
"use strict";
/* Front-end lib */
/*
Message structure (JSON.stringified):
id - identificator
type - method type (get, put, delete, post, notify)
name - event name
data - data object
callback - true/false (to notify whether it's callback)
*/
/* Public part */
function SocketEvent( port ) {
var url = "ws://" + window.location.hostname + ":" + port || "8081";
this._socket = new WebSocket(url);
this._handlers = [];
this._serverHandlers = {};
this._id = 0;
this._socket.onmessage = function(data) {
this._handle(data);
}.bind(this);
};
SocketEvent.prototype.get = function(name, data, callback) {
this._send('get', name, data, callback);
};
SocketEvent.prototype.post = function(name, data, callback) {
this._send('post', name, data, callback);
};
SocketEvent.prototype.delete = function(name, data, callback) {
this._send('delete', name, data, callback);
};
SocketEvent.prototype.put = function(name, data, callback) {
this._send('put', name, data, callback);
};
SocketEvent.prototype.notify = function(name, data, callback) {
this._send('notify', name, data, callback);
};
SocketEvent.prototype.on = function(name, callback) {
this._serverHandlers[name] = callback;
};
SocketEvent.prototype.remove = function(name) {
if( typeof this._serverHandlers[name] !== "undefined" )
delete this._serverHandlers[name];
}
/* Private part */
SocketEvent.prototype._send = function(type, name, data, callback) {
if( typeof name == "undefined" ) return;
var id = this._id;
if( typeof callback !== "undefined" )
this._registerCallback(callback);
this._socket.send(JSON.stringify({
id : id,
type: type,
name : name,
data : data,
error : null,
callback : false
}));
};
SocketEvent.prototype._handle = function(socket) {
var msg = JSON.parse(socket.data);
if(msg.error) this._errorHandler(msg.error);
else if( msg.type === "server-notify") this._handleServerNotify(msg.name);
else if( typeof this._handlers[msg.id] !== "undefined" && msg.callback) {
this._handlers[msg.id](msg.data);
delete this._handlers[msg.id];
}
};
SocketEvent.prototype._handleServerNotify = function(name) {
if(typeof this._serverHandlers[name] !== "undefined")
this._serverHandlers[name]();
};
SocketEvent.prototype._errorHandler = function(error) {
console.error("Got socket error: " + error);
};
SocketEvent.prototype._registerCallback = function(callback) {
this._handlers[ this._id ] = callback;
this._id ++;
};
As for code quality. I would like you to pay attention for two things:
The code quality itself
If it's comfortable to use for the end user
To stay easy
The github project has folder "/demo". There is a simple and working example. You are welcome to clone and try it yourself.