Introduction to Node.js

What is Node.js

Node.js is a platform created by Ryan Dahl, for developing applications for better scalability. Node.js is based on event driven programming model. We can develop server-side and networking application using Node.js software platform. The primary objective of Node.js is to maximize the throughput of the applications, and Node.js uses non-blocking I/O. Node.js promote asynchronous event handling. The programming language used in Node.js to develop applications is JavaScript.

Blocking I/O and Multi-Threaded Programming Models

Before we proceed with even-driven programming style, let us revisit the two programming models and their disadvantages. This way we can better appreciate the value of even-driven programming.

Blocking IO: The traditional blocking I/O programming model has its own disadvantages. In the older days, when doing I/O operations on time-sharing systems, each process corresponds to one user so that users are isolated from each other. In those systems, user needs to finish one operation before proceeding to the next operation. The biggest problem with this kind of model is scalability. The operating system has to take the burden of managing all the processes, and context switching is expensive. Moreover, the system performance degrades after the processes reach certain number.

Multi-threaded Programming: To mitigate the problems associated with traditional blocking I/O programming model, Multi-Threading was introduced. In multi-threaded programming, multiple threads are spawned from one single process which shares memory with other threads within the same original process. The idea behind this model is that, when one thread is waiting for I/O, another thread can take some other task to execute. When the I/O operation finishes, the thread which is waiting for I/O can wake up and resumes processing the tasks. The problem with this multi-threaded programming model is that, programmers do not know the exact behavior of threads and their shared memory state. Programmers have to rely on locking, synchronization and semaphores to control access to data and resources.

Event Driven Programming

A style of programming in which events will determine the flow of execution. Event handlers or event callbacks will handle the events. An event callback is a function that is invoked when something significant happens. For example, we can have an event callback function to be invoked when a new message is available in the messaging queue, or for user triggered events like clicking a button etc.

For example, consider the old fashioned blocking I/O programming way, if we want to retrieve and process data from a database, we’ll do something like:

myData = query(‘SELECT * FROM employees where empId = 1234’);
processMyData(myData);

In the above example, the current thread has to wait until the database finishes retrieving the results.

In the event-driven programming style, the same scenario can be achieved like this:

myDataRetrieved = function(myData) {
processMyData(myData);
}
query(‘SELECT * FROM employees where empId = 1234’, myDataRetrieved);

In the above event-driven example, we are first defining what is going to happen once the query is finished, and we are storing the query results in a function named ‘myDataRetrieved’. Then we are passing that function as an argument to the query. When the query execution is finished, the query will invoke the function ‘myDataRetrieved’ (which essentially processes the data), instead of simply returning the result.

In this style of programming, instead of simply returning the results, we define functions that are invoked by the system when significant events occur (in our case data is retrieved and ready to use). This style of programming is called ‘event-driven programming model’ or ‘asynchronous programming’. This model is the fundamental aspect of the Node.js. The core idea behind this programming model is that, current process (or thread) will not block when it is doing I/O. Therefore, multiple I/O operations can occur in parallel, and each operation has its own callback function which will be invoked once respective operation completes.

How event-driven programming is achieved

The event-driven programming is achieved through a concept of ‘event loop’. Essentially, an event loop performs two operations in a continuous loop. These two operations are event detection and event handling. In each run of the loop, it has to detect what are all the events fired, and then determining respective event callback and invoking the callback.

This event loop runs as a single thread inside a single process. Due to this fact, programmers can relax the synchronization requirements and do not have to worry about concurrent threads accessing common resources and sharing same memory state.

How clients handle asynchronous requests

Consider the following example of jQuery performing an Ajax request using XMLHttp-Request (XHR):

$.post('/myData.json', function(data) {
console.log(data);
});

In the above code example, the I/O operation doesn’t block execution. This program performs an HTTP request for myData.json. When the response comes back, an anonymous function is called (the callback in this context) containing the argument ‘data’, which is the data received from that request.

The response for myData.json would be stored in the ‘data’ variable when it is ready and that the console.log function will NOT execute until then.

The I/O operation (the Ajax request) would block script execution from continuing until ready. Because the browser is single-threaded, if this request took 500 milliseconds to return, any other events happening on that page would wait until then before execution. User experience will be bad if an animation was paused or the user was trying to interact with the page during this waiting period.

In this case, fortunately things are not blocked. When I/O happens in the browser, it happens outside of the event loop (outside the main script execution) and then an event is emitted when the I/O is finished, which is handled by a function (often called the callback).

The I/O happens asynchronously and doesn’t block the script execution, allowing the event loop to respond to whatever other interactions or requests are being performed on the page. This enables the browser to be responsive to the client and to handle a lot of interactivity on the page.

There few exceptions that block execution in the browser, those are alert, prompt, confirm and synchronous XHR. Usage of these is not recommended unless application really demands.

How server handles asynchronous events

The following is a PHP example of traditional I/O blocking model.

$result = mysql_query('SELECT * FROM myTable');
print_r($result);

In the above example, program execution blocks until database query completes execution. This code does some I/O, and the process is blocked from continuing until all the data has come back. Though this model is fine for many applications, but the process has state, or memory, and is essentially doing nothing until the I/O is completed. That could take anywhere from 20ms to minutes depending on the latency of the I/O operation.

Typically, while waiting for I/O the server does nothing. One solution to this problem is to use multithreading. But the multithreaded applications are complex and hard to code and manage, also expensive in terms of CPU utilization and execution.

In Node, I/O is performed outside of the main event loop, allowing the server to stay efficient and responsive. This makes it much harder for a process to become I/O-bound because I/O latency isn’t going to crash your server or use the resources it would if you were blocking. It allows the server to be lightweight on what are typically the slowest operations a server performs.

DIRTy applications and Node.js

Node.js is specifically designed for Data Intensive Real-Time applications or simply ‘DIRT’ applications. A Node server is asynchronous and event driven, holds number of I/O connections open, while simultaneously handling many requests with low memory footprint. Node applications are lightweight on I/O, and highly responsive. Node is a powerful platform for data intensive, highly responsive and real-time applications. Node core is small, simple and contains building blocks for I/O based applications. There are many third party modules built upon core module to offer greater abstractions. ‘Express’ is a popular Node.js framework.

Installing Node.js

Installing Node.js is pretty straightforward on most operating systems. Node can be installed either using package installers or using command line tools. Of course, command line installation is easy for Unix/Linus platforms. As learners, we always wanted to install on our Windows systems. So in this article, let us install Node in Windows. However, from time to time, we need to use Node Package Manager (npm) to find and install required add-ons.

Node standalone installers are available here. Please download the appropriate version for your Windows (32bit/64bit) and double clicks on the installers. The installation process is simple and self-explanatory (You can find installation instructions in our bower tutorial). Once Node is installed successfully, we should be able to run Node and npm from the command prompt.

Verifying Node.js installation

In order to verify whether Node is successfully installed, please go to command prompt and execute the following commands. The first command displays the Node version installed and the second command displays sample test output to screen.

Assuming we installed Node under D:\work\nodejs …

1

Press Ctrl+C couple of times to exit from the Node prompt.

Also, the folder structure should look similar to the following screen capture once the Node is successfully installed on the Windows.

NodeJS Directory

Node.js Application By Creating Node HTTP Server

Building servers is very common in Node. We can create different types of servers using Node. This is slightly strange especially if we come from the server background where we use servers like Apache or Nginx etc. However, in Node we can logically think that server and application are same. The following code example creates a HTTP server which responds to requests.

It is always best option to keep application specific files or applications separate from Node installation. Since we already installed Node under D:\work\nodejs, let us create a separate folder under D:\work called node-apps. Inside node-apps create an application folder called hello-node. Then, create a file called server.js and type the following code in the server.js file.

var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type':'text/plain'});
response.end('Welcome to Node platform.\n');
}).listen(3000);
console.log('Server running at http://localhost:3000/');

Once our server.js file is ready, go to command prompt to location where the server.js file resides (D:\work\node-apps in this case), and execute the following command to start the server.

D:\work\node-apps\hello-node>node server.js

The Node HTTP server should start listening on port 3000 as shown in the following screen capture.

Running NodeJS

Now, open any browser and type the following to test our first Node application.

http://localhost:3000/

We should be able to see the sample output as shown below.

NodeJS Example

So whenever a HTTP request arrives on the configured port (3000 in our example above), the call back function is triggered with request and response as arguments. Inside this function we are specifying the HTTP Status code to returned (200), and Contet-type as text/plain in the response object. Finally, we are ending the response with a message which displays on the browser.

Comments

comments

Speak Your Mind

*