Node.js – How to Pass a Socket.io Socket Between Modules and How to Export a Socket.io (io) Instance for Emitting Socket.io Events From Another Module

I have been working on Node.js and Socket.io for some time. Lately I wanted to learn about alternative database solutions on Node.js and I started to work on mongodb, which seems to be one of the most popular DB solutions for fast and scalable DB applications to be used with fast Http servers like Node.js.

Before diving deep into the mongodb world I got stuck with a problem for some time and did not want to move forward before sorting it out. Here is the task I had some problem achieving, and my solution to it.

TASK

Send user data like username, email etc. from the client to the node server on a socket.io event, on the server-side check if the username exist in your mongodb collection, emit “UserExists” event to the requesting socket if username exists, otherwise record the new userdata in mongodb and emit “UserRecorded” event to the socket making the request.

While doing this, keep the Socket.io (say Messaging.js) part and mongodb (say myMongo.js) part as seperate .js files. For the sake of having a clear and maintainable code base.

SOLUTION (Code Structure/ Logic)

1) Messaging.js

Messaging.js is mainly responsible for the event handling between client(s) (socket) and server using socket.io. Receives events from clients, processes the data received, emits events back to the client(s) according to the results obtained on the server-side.

Messaging.js will have the following main declarations in it:

var myMongo = require('./myMongo.js'); //we will be using a method from myMongo.js

var http = require('http'); //required to created a Node.js Http Server

//create Node Http Server
var myServer = http.createServer(function (request, response) {
request.on(“end”, function() {
// request ended normally, can do something here
});
});
//make socket.io work with myServer (which is a Node Http Server)
var io = require('socket.io').listen(chatServer);
//make myServer listen to port 8080
myServer.listen(8080, function () {
console.log(“My Server listening on port 8080.”);
});

//below event (newsignup) is emitted from client-side when a button is clicked, containing the user data

socket.on('newsignup',function(data){
myMongo.checkUserName(data.UserName, data.Email, data.PassWord, 'testdatabase', socket);
});//->this is where you pass the Socket to “checkUserName method in myMongo.js”

//We will be using this io instance in myMongo.js together with the socket that is passed above to
//checkUserName method in myMongo.js
module.exports.io=io;


So, you need to;
a) Pass the “requesting socket” to the checkUserName method defined in myMongo.js
b) Export the io instance so that it can be used by myMongo.js module.

2) myMongo.js

Mongo.js is mainly responsible for recording documents in mongoDB collections, querying collections and other CRUD operations.

myMongo.js will have the following main declarations in it:

var Messaging = require('./Messaging.js');//because we will be using the exported io instance

//
//skipping db declarations here they are not related to this post
//

//Below is the function we called before from Messaging.js (above, remember?)

function checkUserName(username, email, password, tablename, socket) {
db.collection(tablename).findOne({ UserName: username }, function (err, item) {
if (err) {
return console.dir(“(ERR)” + err + ” UserName check failed”);
}
else {
if (item != null) {
console.log(“(USEREXISTS)” + item.UserName);
//use the io instance exported from Messaging.js and the socket passed as argument
//from the method call in Messaging.js AND emit relevant event to the requesting socket
Messaging.io.sockets.socket(socket.id).emit('UserExists', { UserName: username });
}
else {
console.log(“(NOUSEREXISTS)” + username);
RecordUser(username, email, password, 'testdb3');//record the data if username does not exist

//use the io instance exported from Messaging.js and the socket passed as argument
//from the method call in Messaging.js AND emit relevant event to the requesting socket

Messaging.io.sockets.socket(socket.id).emit('UserRecoreded', { UserName: username });
}
}
});
}


That is pretty much it.

Let's see briefly what we are doing here:

-Client clicks a button emitting an event and some data to the server-side
-This event and data is received from the socket.io end (Messaging.js) of our server-side node.js application
-Socket.io end of our server-side code invokes a method (checkUserName), which is defined in mongodb end (myMongo.js) and was already exported from the mongodb end of our server-side Node.js application
-This method is supplied with the requesting “socket” as one of its' arguments while being invoked on the socket.io end of our application
-Socket.io end of our application exports Socket.io (io) instance
-UserName value is checked on the mongodb end of our server-side application (checkUserName)
-Exported io instance and the “socket” which is passed as an argument to the checkUserName method are used to emit the relevant socket.io event after querying our mongodb collection on the mongodb end of our application

CONCLUSION

Even if you split your server-side Node.js code for a clear & maintainable code structure, you can carry different abilities between your different .js modules as I did here by exporting an io instance (yes that is what I call it) and passing a “socket” as an argument.

Hope this helps someone.

Good luck,
Serdar.

Leave a Reply

Your email address will not be published. Required fields are marked *