Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
2  
As we all want to make our code more efficient or improve it in one way or another, try to write a title that summarizes what your code does, not what you want to get out of a review. Please see How to get the best value out of Code Review - Asking Questions for guidance on writing good question titles. – Dan Pantry Jan 15 at 10:07
    
README are not up for review since they're not code. Please add to the question what your module is doing. This should help getting quality reviews. – Mast Jan 15 at 12:14
    
Just updated. Added readme (short version). – Lazyexpert Jan 15 at 12:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.