Load More – Introducing Node.js and Socket.io (Part 2)

Continuing the Load More series by introducing Node.js and Socket.io. This part is very detailed and easy to understand introduction to these two technologies. Each and every line of sample programs is explained assuming reader don’t know anything about JavaScript, Node.js, and Socket.io.

Other Parts

Source Files

Let’s review what was Part 1 about? Currently there are two techniques for displaying large number of records. First one is pagination and everyone knows about it because it’s implemented in most of the web apps. For example Google implemented it in their search engine. The second technique is Load More. Now in this technique the data isn’t displayed in pages. The first set of data is loaded on first page load. The next set is loaded when user clicks on Load More button. Similarly user can click the button again and again until all the data is loaded in that single page. Check the demo from Part 1 to better understand how it works.

So in Part 1, I showed you how to implement the Load More technique using KnockoutJS and CodeIgniter. In the upcoming parts of this series I will show you how to get the newly added records in real time. Let me give an example of Twitter. When other users to whom you have subscribed tweet some message(s), a notification appears saying “X new Tweets…” (where X is the number of new tweets). When you click that notification, it displays those newly added messages. They did this for usability instead of directly displaying the new tweets. This is exactly what we are going to build.

New Tweets in Twitter

We will be using Node.js, and Socket.io for implementing this functionality and in this Part, I will introduce you to these two technologies so those of you who don’t know about them get an introduction what is Node.js and Socket.io and how to create some sample programs. These sample programs will use concepts which will focus primarily on what we will develop in the Part 3.

Introduction to Node.js

So what’s Node.js? First Node.js is a serverside technology and the code which you are going to write will run on server. Look at the .js part in its name. This means that the language which you are going to use will be JavaScript. You will be writing serverside JavaScript to create Node.js programs.

Following lines are taken from Node’s home page and these lines define exactly what Node is. So I am gonna explain these lines in detail.

“Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.” – nodejs.org

Chrome’s JavaScript runtime:
What they mean by Chrome’s JavaScript runtime? Chrome as we know is a browser from Google. They are saying that they have used V8 engine (which is JavaScript runtime used in Chrome) for compiling JavaScript code. You maybe wondering why I wrote compiling? Actually modern JavaScript engines no more interpret code like they used to do before. Modern engines compile js code to native machine code. So the performance of js code is almost equivalent to languages like C/C++ which’s a huge performance gain.

easily building:
Writing realtime network application in Node.js is really really easy. Thanks to JavaScript for that. You can’t understand how easy it’s unless you don’t program yourself in it.

fast, scalable:
Node.js apps are really fast because they are single threaded unlike Apache or IIS which creates a new thread for every request. So this means Node.js apps will also consume much less memory compared to applications running in Apache or IIS. Because it’s single threaded so it’s highly scale able. There’s are other reasons for its scalability like non-blocking I/O, and event driven which are explained below.

network applications:
Of course Node.js applications will always be network applications. In Node.js you will be writing servers which listen to client requests and responds accordingly. This is not like a PHP or ASP.NET application which runs in Apache or IIS server. Node.js apps are itself servers so they don’t need any server software in which you can host it.

an event-driven
In Node.js code is not executed in sequential order like in languages C/C++, C#, PHP, or Java. It runs in an event-driven manner. There’s an event loop in JavaScript which always wait for the events to happen and when an event occurs it trigger a callback against that event.

non-blocking I/O model
Every I/O you perform using Node.js will be non-blocking. For example if you execute a query against a database. It will not wait for the response from the database server and it will continue executing the code after the line on which query is executed. When the response from database server is received, event loop will automatically call a callback which will do the processing on data it received from database.

data-intensive real-time applications
Node.js is best for data-intensive applications which perform lot of I/O. It’s not good for compute-intensive apps. You can develop real-time applications with node pretty easily because Node is fast, scalable and it has event-driven model.
Note: Actually there are workarounds for making good compute-instensive apps with multi-threading in Node.js.

run across distributed devices:
Any client application (web, mobile, or desktop or even other Node.js apps) in any device can communicate over a network with the Node.js applications.

Installing Node.js

Visit nodejs.org and click on Download button. Windows and Mac users can download the installers but Linux user must use package managers to install Node.js. Check Installing with a Package Manager link and there you can find ways to install Node.js on most popular Linux distros using package managers.

To test your installation simply open Command Prompt in Windows or Terminal in Mac or Linux. Now type the command “node” and if you are entered in REPL (Read Evaluate Print Loop) mode showing > sign, it means you have successfully installed Node.js. REPL mode is similar to Firebug’s console in which you an run scripts directly. For example you can create an array, add an item, and print it on the screen etc. Press CTRL+C twice to exit REPL mode.

Hello World Server

Let’s take a look at an example program of Node.js. This example will be an http server which listens to client requests and send “Hello World!” as a response. Let’s start writing our first Node.js http server:

var http = require( 'http' );

The first line is like require/include in PHP, using in C#, or import in Java. This line is actually getting http module and assigning it http variable.

var server = http.createServer();

Above line creates an http server using createServer method and assign it to server variable.

server.listen( 8000 );

Then listen to port 8000 for the coming requests.

Whenever we run Node.js program, it first executes the code in sequential order and attach callbacks to different events. This is the initialization phase. After that everything will be event-driven. Above three lines will execute in sequential order when we first run this program. When we created the server on 2nd line, we need to define a callback which will run whenever a request is received from the client and this callback will handle the request and send whatever response is required. So let’s define the callback.

var server = http.createServer( function( req, res ) {
 
});

Callback will be an anonymous function which has no name and passed as parameter to createServer. Note that functions can be passed as parameters in JavaScript. This function also accepts two parameters. req (Request) and res (Reponse). For our example we will use only res parameter to send header information and “Hello World!” text as response. Write following two lines in the callback.

//http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
res.writeHead( 200, { 'content-type': 'text/plain' });
res.end( 'Hello World!' );

After initialization phase node will always be waiting for requests and when a request is received, this callback will execute. Now this call will write header information sending an http status code of 200 which means successful response is sent. Content-type defines the type of response we are going to send. In our case we are sending the text “Hello World”. Here’s the final program listing.

var http = require( 'http' );
 
var server = http.createServer( function( req, res ) {
    //http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
    res.writeHead( 200, { 'content-type': 'text/plain' });
    res.end( 'Hello World!' );
});
 
server.listen( 8000 );

Let’s test this simple server. To run this program, type node hello_world.js in terminal. Now open the browser and type http://localhost:8000. If it displays “Hello World!”, then viola! Your sever is running fine :)

Introducing Socket.io

Of course in the next part I will show to some more useful examples related to Node.js but before that let me introduce you to Socket.io.

Socket.io is Node.js module (like http is a module) which provides functionality to create web sockets to allow realtime communication between client and server. A socket is an end-point for communication and it’s represented by an IP address and Port No separated by colon. e.g. 127.0.0.1:8000.

A web socket means a socket for communication over the web. Many people think that Socket.io is used to create HTML5 Web Sockets. But that’s not true because socket.io works in every desktop and mobile browser and even in those which don’t support HTML5. So how could it be possible that Socket.io creates HTML5 Web Sockets behind the scene? Actually Socket.io provides support for every browser by checking the existence of particular technologies until it find the one which works for the current browser.

It first checks the presence of HTML5 Web Socket and make use of it. If it’s not present, it checks whether Adobe Flash Player is installed? If yes then it make use of Flash Sockets. Similarly it check for the presence of technologies or techniques until it finds the one which will work for the current browser.

So Socket.io makes use of HTML5 Web Socket but you can’t say that it’s HTML5 Web Socket. It’s more than that.

Installation of Socket.io

As I said before that Socket.io is Node.js module and to install modules, you need to make use of npm (Node Package Manager) command. Type this command to install it.

npm install socket.io

Socket.io Chat Server Example:

Let’s take a look at an example chat server program which make use of Socket.io.

var io     = require( 'socket.io' )
  , server = null;
 
server = io.listen( 8000 ).set( 'log level', 1 );
 
server.sockets.on( 'connection', function( socket ) {
    socket.on( 'msg', function( data ) {
        socket.broadcast.emit( 'incMsg', data );
    });
});

I tried to define as many variables as I can to make the code clear and easy to understand. First add Socket.io module using require function and define server variable with null assigned to it.
Then let’s start listening to port 8000 and this method will return a server object that will be used later to add connection event and then set method is called to set its log level to 1. This means that it will not log the details on terminal. Note that I used chaining here. First listen will be called and then set will be called on the server object which is returned from listen method and finally it will be assigned to server variable.

Then I added a connection event to our server and this event will fire whenever a new client will try to connect to our server at port 8000. To add connection event, I wrote server.sockets.on( ‘connection’ ). Then I passed a callback as second parameter which will be fired when a new client will try to connect to our server. The parameter in the callback will be socket. This socket parameter is used to add the events for the client which is trying to get connected to our server. Then within callback msg event is added using socket.on method. You will see later that all the communication b/w client and server will take place using events. When a client want something to happen on server, it will send an event to the server along with the optional data. Suppose our client sends a msg event to our server, it will receive on this line ( socket.on(‘msg’) ) and then a callback will fire with data as parameter.

Let me give you some background when msg event will be fired from client. As I said before we are creating a simple chat server and obviously user will type some text in the textbox and hit enter or click on send button. The code in client’s browser will generate a msg event with text from textbox as data and send it to server. As soon as the server received the msg event with data, it will fire a callback with the data containing text as parameter. So now within the callback, text from client is broadcasted to all the other clients which are connected to this server. It’s very simple to do because there’s a built in method for broadcasting the message to other users. To broadcast, emit method is used: socket.broadcast.emit( ‘incMsg’, data ). It will send an event “incMsg” to all the other connected clients but not itself along with the data which is obviously the text sent from the client.

Creating the Client

Ok that’s it. That’s the only code required to implement a simple chat server with Node.js and Socket.io. Let’s create a simple client that can send and receive messages from this server. Create an HTML file with three controls.

<input type="text" id="txt_msg" /> 
<input type="submit" id="btn_send" value="Send" /> 
<p><textarea id="txt_output" rows="20" cols="80" readonly="readonly"></textarea></p>

Before writing the client script, let’s run our server from the terminal (using command “node socket.io.js”) because I want to explain few things here. First you can test whether you server is running or not from the browser. Enter http://localhost:8000. And it must display “Welcome to socket.io.” in the browser. It means everything is running fine. Now the important thing is socket.io generates a client script which must be added in our page to make use of socket.io APIs and including this script file is mandatory to make the client functional. To access this script file you need to use this URL “http://localhost:8000/socket.io/socket.io.js”. The name of server and the port on which server is listening to, then socket.io/socket.io.js. Hit enter and you will see a long script displayed in browser. Simply add this script in the webpage.

<script src="http://localhost:8000/socket.io/socket.io.js"></script>

Now add custom script to make the client functional.

document.addEventListener( 'DOMContentLoaded', function() {
    var socket = io.connect( 'http://localhost:8000' )
      , txt_msg = document.getElementById( 'txt_msg' ) 
      , btn_send = document.getElementById( 'btn_send' ) 
      , txt_output = document.getElementById( 'txt_output' ); 
});

First add a DOMContentLoaded event using addEventListener which will fire when parsing of page completes.

Then within the event handler, create a connection using io.connect method. This io object is defined in the script file which we included above. We pass the URL where the server is hosted. Then let’s cache some DOM elements in variables.

Now we need to send text message to server using two ways. First when user types in the text and press enter key. Second is when user clicks the Send button. First add an event listener to Send button which will call sendMsg() function as shown below.

document.addEventListener( 'click', function() {
    sendMsg();
});

Now add a keypress event so when user will type the message and hit enter, it must send the text to server in that case as well. Add keypress listener to txt_msg. Check the keyCode if it’s 13 which means Enter is pressed.

document.addEventListener( 'keypress', function( e ) {
    if( e.keyCode === 13 ) { //if enter is pressed
        sendMsg();
    }
});

Now define sendMsg function.

function sendMsg() {
    socket.emit( 'msg', txt_msg.value );
    txt_msg.value = '';
}

Within this function we will emit a “msg” event with the text entered in text box. This will send an event along with the data to server. Then we clear our text box.

When “msg” event is received on server, it will broadcast it all other clients using incMsg event. So we need to receive this event on our client.

socket.on( 'incMsg', function( data ) {
if( data !== '' ) 
    txt_output.value += data + '\n'; 
});

To add an incMsg event, we need to write socket.on and pass event name and callback with the data received from server. Before displaying the text received from server, check if it’s not empty. Then display it in textarea. Now your final script must look like this:

document.addEventListener( 'DOMContentLoaded', function() {
    var socket = io.connect( 'http://localhost:8000' )
      , txt_msg = document.getElementById( 'txt_msg' ) 
      , btn_send = document.getElementById( 'btn_send' ) 
      , txt_output = document.getElementById( 'txt_output' ); 
 
    socket.on( 'incMsg', function( data ) { 
        if( data !== '' ) 
            txt_output.value += data + '\n'; 
    });
 
    document.addEventListener( 'keypress', function( e ) {
        if( e.keyCode === 13 ) { //if enter is pressed
            sendMsg();
        }
    });
 
    document.addEventListener( 'click', function() {
        sendMsg();
    });
 
    function sendMsg() {
        socket.emit( 'msg', txt_msg.value );
        txt_msg.value = '';
    }
});

Load this client page using any server (like Apache or IIS) instead of directly executing it browser using URI file://. It will not work that way. Open the client in two or three browser windows and try typing some text and send. You will see that all clients will receive the text in realtime.

Node.js and Socket.io Chat Server

In the next part will built exact replica of Tweeter functionality using Node.js and Socket.io and we will also modify our code from Part 1 to incorporate the new changes. Don’t forget to subscribe via Email or RSS to get the latest updates.


comments powered by Disqus