Showing online users using Nodejs and Socket.io

In any Real Time chatting app showing a number of online users play very important role, which need to be updated when a new user comes online or an online user goes offline. So this article explains how we can create such a list of online users.

Here am using NODEJS for server-side, AngularJs for client-side and Socket.io for real-time updates.The figure shown below explains the working of this module.

Also, read Typing notification in chatting application using nodejs and socket.io

showing number of online user workflowHere is our package.JSON file.

package.JSON

{
  "dependencies": {
    "express": "4.13.3",
    "express-session": "1.12.1",
    "body-parser": "1.14.1",
    "socket.io": "1.3.7",
    "mysql": "2.9.0"
  }
}

Now creating the server.js file for our application.Which consist of functions getting a list of an online user, integration of socket.io for real-time updates and method for login registration.

server.js

var app = require("express")();
var session = require('express-session');
var mysql = require("mysql");
var bodyParser = require('body-parser');
var http = require('http').Server(app);
var io = require("socket.io")(http);


//initialize the session
app.use(session({
    secret: "online",
    resave: true,
    saveUninitialized: true
}));
var session_data;


app.use(require("express").static('data'));

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

/* Creating MySQL connection.*/
var con    =    mysql.createPool({
      connectionLimit   :   100,
      host              :   'localhost',
      user              :   'root',
      password          :   '',
      database          :   'angular'
});


app.get("/",function(req,res){
    res.sendFile(__dirname + '/index.html');
});


/*  Socket connectes ur machine to server */
io.on('connection',function(socket){  
    socket.on('update_list',function(data){
      //data.purpose;
      
      
      if((String(data.purpose.trim()))=='login'){
        var query="update user set online = ? where id = ?";
        con.query(String(query),['Y',data.id],function(err,rows){
         // var query="select * from user where id !='"+data.id+"'";
          var query="select * from user";
          con.query(String(query),function(err,rows){
            io.emit('logout update',JSON.stringify(rows));
          });
        });
      }else{
        var query="update user set online = ? where id = ?";
        con.query(String(query),['N',data.id],function(err,rows){
          //var query="select * from user where id !='"+data.id+"'";
          var query="select * from user";
          con.query(String(query),function(err,rows){
            io.emit('logout update',JSON.stringify(rows));
          });
        });
      }
    });
});

app.post('/login', function (req, res) {
  session_data=req.session;
  //console.log(req.param('name')); // depricated
  data = {
    name:req.body.name,
    password:req.body.password,
  };
  session_data.password=data.password;
  session_data.name=data.name;
  var obj={};
  var query="select * from user where name='"+data.name+"' and password='"+data.password+"'";
      con.query(String(query),function(err,rows){
        if(rows.length > 0){
          var un=new Buffer(String(rows[0].name)).toString('base64');
          var ui=new Buffer(String(rows[0].id)).toString('base64');
          obj.path_name="/home.html#?un="+un+"&ui="+ui;
          res.write(JSON.stringify(obj));
          res.end();
        }else{
          obj.path_name="invalid";
          res.write(JSON.stringify(obj));
          res.end();
        }
    });
});

app.get('/home', function (req, res) {
  session_data=req.session;
  if(session_data.name){
    res.sendFile(__dirname + '/data/home.html');
  }else{
    res.redirect('/');
  }
});

app.post('/get_list', function (req, res) {
  var query="select * from user";
  con.query(String(query),function(err,rows){
    res.write(JSON.stringify(rows));
    res.end();
  });
});

app.post('/logout', function (req, res) {
  var query="update user set online = ? where id = ?";
  con.query(String(query),['N',req.body.id],function(err,rows){});
  req.session.destroy(function(err){
  res.end();
  });
});


http.listen(8080,function(){
    console.log("Listening on 8080");
});

Creating home.html which uses Angularjs to manage the data.

home.html

<html ng-app="home">
  <head>
    <title>Socket.io</title>
    <script src="/socket.io/socket.io.js"></script>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/font-awesome.min.css">
    <link href="css/style.css" rel="stylesheet" >
  </head>
  <body ng-controller="home">
    <div class="container">
      <div class="panel panel-default">
        <div class="header_info panel-heading">
          <div class="rows">
            <div class="col-md-8 ">
              <p class="welcome_user">Hello {{name}}</p>              
            </div>
            <div class="col-md-2 ">
              <div class="logout_btn">
                <a id="logout"  ng-click="logout()">Logout</a>
              </div>
            </div>             
          </div>
        </div>
        <div class="panel-body">
          <div class="rows">
            <div class="col-md-12 list_con">
              <center><span>List of Online People</span></center>
              <div class="col-md-8 person_list" ng-repeat="person in persons" hello="{{uid}}" ng-style="{
                                'display': person.id==uid ? 'none' :'block'
                        }">
                <img src="/img/{{person.p_photo}}" class="img-circle profile-photo" />
                <span>&nbsp;{{ person.name }}</span>
                <span class="online" ng-style="{
                                'background-color': person.online=='Y' ? '#0EE700' :'red'
                        }">&nbsp;</span>
              </div>
            </div>            
          </div>
        </div>
      </div>
    </div>
  </body>
  <script src = "js/jquery.min.js"></script>
  <script src = "js/bootstrap.min.js"></script>
  <script src = "js/angular.min.js"></script>
  <script src = "js/home.js"></script>

The final output looks like this,

Showing online users using Nodejs and Socket.io exmaple

Now creating the script for home.html which consist of the integration of socket.io and function to fetch a list of users.

Script.js

var app = angular.module('home',[]);
app.controller('home', function ($scope,$http,$window,$location) {    
    var socket = io();

    // decoding of base64
    $scope.name=atob($location.search()['un']);               
    var id=atob($location.search()['ui']); 
    $scope.uid=id;        
    
    $http.post('/get_list', {}).success(function(data, status, headers, config) {
            var data_server={purpose:"login",id:id}
            socket.emit('update_list',data_server);
        }).error(function(data, status) {
            console.log("Connection Error");
            alert("Connection Error");
        });
    $scope.logout=function(){    
        $http.post('/logout', {id: id}).success(function(data, status, headers, config) {
            var data_server={purpose:"logout",id:id}
            socket.emit('update_list',data_server);
            $window.location.href="http://127.0.0.1:3000/"
        }).error(function(data, status) {
            console.log("Connection Error");
            alert("Connection Error");
        });
    }
    socket.on('logout update',function(data){
        $scope.persons=JSON.parse(data);
        $scope.$apply(); 
    });

If you like this article considers sharing with other hoodies.

  • xfg

    What if the process will be terminated unexpectedly? After restart process old users will be yet marked as online.

    • Nice catch, I’ll update this code.

      • xfg

        Is there any progress in this issue? What if the application is running within the node cluster, i.e. 2 or more processes and one of them died?

      • Brijesh prajapati

        how to run the app i m getting error when trying to login..
        in server.js line no 80. says can’t use the undefined property length