When I started working on NodeJS, I had no prior experience nor knowledge about NodeJS nor about Javascript. It was kind of a painful journey, considering the fact that I was migrating myself from a structured programming which deals with linear method of programming to something which is asynchronous.

Many may argue that by using threads we can achieve asynchronous behavior of the executed code, however when we really start looking into NodeJS as a noob, we come across various pitfalls. In order to explain this in a much better manner, let us view the codes written in C and NodeJS, both of which are doing the same task, ie., writing data into a file.

Source Code of a common C program to write files:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    FILE *fp;
    int i;
    fp = fopen("c:\test.txt", "w");
    if (fp == NULL)
    {
        printf("Error opening test.txt for writing.n");
        exit(0);
        }
    for (i=0; i<5; ++i){
    fprintf(fp, "%d, %dn", i, i*i);
    printf("%d, %d in Loopn",i, i*i);
    }
    printf("%d Out of Loop.n", i );
    fprintf(fp, "%d Completed Loopn",i);
    printf("%d Completed Loop.n", i );
    i = 888;
    printf("%d Value of i.n", i );
    getch();
    return 0;
}

Source code of a program written in NodeJS. In this NodeJS code, I have added some console output code so as to understand the functional working of Asynchronous Coding. Keep a tab on the value of “i” and observe the changes as this code gets executed.

var fs = require('fs');
for (var i=0;i<5;i++){
	fs.appendFile("nodejs.txt", i + ', ' + i*i + 'n', function(err) {
		if(err) {
			console.log(err);
		} else {
			console.log(i + ', ' + i*i + " In Loop!");
		}
	});
}
console.log(i + ', ' + i*i + ' Out of Loop');
fs.appendFile("nodejs.txt", i+' COMPLETED LOOPn' , function(err) {
	if(err) {
		console.log(err);
	} else {
		console.log(i + " Completed Loop!");
	}
});
i = 888;
console.log(i + " Value of i!");

From the point of view of a programmer who has worked on structured languages, at first glance I would admit that both the codes should at the end of execution provide a file which contains the value of “i” and its square, while at the end of the execution the file should be written with “Completed Loop”, and just prior to the termination the value of “i” would be modified. However, after the actual execution, both the console outputs differ from each other, and moreover, based on the console output, we observe that the control of the execution in NodeJS is strikingly different than that of C, and also in between the execution the value of “i” has changed.

From the console output of NodeJS it is quite evident that even before the “for loop” can finish its logical execution, ie. writing of the file content, the next-in-line statement was executed, and along with this the value of “i” was changed. This effectively has affected the functional / logical aspect of the program.

Even though the values to be written in the file were unchanged, it simply demonstrates the fact that when dealing with asynchronous programming, the value of the variables are dependent on the manner in which the code gets executed and not where they are placed, as it is in the case with C or other languages. Also, the behavior of asynchronous functions is quite different when compared with the form of coding / code execution most of us are used to.

Want to learn more?? The InfoSec Institute CISSP Training course trains and prepares you to pass the premier security certification, the CISSP. Professionals that hold the CISSP have demonstrated that they have deep knowledge of all 10 Common Body of Knowledge Domains, and have the necessary skills to provide leadership in the creation and operational duties of enterprise wide information security programs.

InfoSec Institute's proprietary CISSP certification courseware materials are always up to date and synchronized with the latest ISC2 exam objectives. Our industry leading course curriculum combined with our award-winning CISSP training provided by expert instructors delivers the platform you need in order to pass the CISSP exam with flying colors. You will leave the InfoSec Institute CISSP Boot Camp with the knowledge and domain expertise to successfully pass the CISSP exam the first time you take it. Some benefits of the CISSP Boot Camp are:

  • Dual Certification - CISSP and ISSEP/ISSMP/ISSAP
  • We have cultivated a strong reputation for getting at the secrets of the CISSP certification exam
  • Our materials are always updated with the latest information on the exam objectives: This is NOT a Common Body of Knowledge review-it is intense, successful preparation for CISSP certification.
  • We focus on preparing you for the CISSP certification exam through drill sessions, review of the entire Common Body of Knowledge, and practical question and answer scenarios, all following a high-energy seminar approach.

NodeJS applications are designed to maximize throughput and efficiency, using non-blocking I/O and asynchronous events. NodeJS applications run single-threaded, although NodeJS uses multiple threads for file and network events.

A brief look into the introduction of NodeJS is sure enough to make us realize that we indeed need to change our perspective while coding in NodeJS. Hence, those vying to switch over to NodeJS should bear in mind the intricacies of Asynchronous programming. The above mentioned issue is just one of the many which we may come across, in case we do not understand the basic concepts of NodeJS and the methods that need to be used to successfully write a piece of code / complete a project in NodeJS.

For beginners, one may come across lots of websites which help in making you understand NodeJS, however over here in this article we will be taking a look in some other aspects which are necessary for a beginner when they straightaway start working on NodeJS.

Before we proceed, let us explore some concepts related to:

1: Strings and Arrays
2: Callbacks

String and Arrays

A small piece of code will give you a simple walkthough of strings, arrays and objects.

var string = 'TestingString' ;
var array = ['0',1,'Two','Three','Four'] ;
for (var i=0;i<5;i++){
console.log(i + ',' + '-'+ string[i] + '-' + string.indexOf(string[i]) + '-' + typeof(array[i]) + '-' + array[i][0]);
}
console.log('-----');
array.forEach(function(value) {
  console.log(value, ':' ,typeof(value));
});
console.log('-----');
var items = [ { id: 1 }, { id: 2}, { id: 3}, { id: 4 }];
console.log( typeof(items[1]) + ' -- ' + items[1],items[1].id);
console.log( items[1]);

Output:

0,  - T - 0 - string - 0
1,  - e - 1 - number - undefined
2,  - s - 2 - string - T
3,  - t - 3 - string - T
4,  - i - 4 - string - F
-----
0 : string
1 ':' 'number'
Two : string
Three : string
Four : string
-----
object -- [object Object] 2
{ id: 2 }

The above example is self explanatory and shows most of the methods used for defining / manipulating strings, arrays and objects. While switching over to NodeJS, knowledge of JavaScript is a must – without it, you would lost in the Garden of Eden.

Traversing through an array can be accomplished either by way of a conventional “for()” loop or using “forEach()”. Moreover, String operations are similar to arrays, and to make the matters worse, a string can dynamically hold any data type, ie. number / string. Hence, while coding, maintain a strict naming convention and keep a tab on the data types of the values that are associated with a particular variable. These small tips shall help you tide over while trouble-shooting. Utilize “typeof()” to verify the data-type and also remember to use JSON.stringify() / JSON.parse() whenever you encounter an array or object. However the basic rules remain the same – Non-Blocking I/O and Asynchronous.

CallBacks

NodeJS uses callbacks to a great effect, and JavaScript programmers are well aware of its functioning. Also ,most of the functions use callbacks, and on numerous occasions you would realize that without callbacks some of the tasks are simply not possible.

Let us first take a look at the skeletal structure of the callback, and then we can use this to either write our own functions or utilize the callbacks rather more efficiently.

//call the function
var num1 = 10;
var num2 = 6;
var num = user_defined_function(num1,num2, function(num) {
	// this function will run when the callback is called
	num = num + 7;
	console.log("callback value: " + num);
});
 console.log('return',num);
//*******************************************//
//define our function with the callback argument
function user_defined_function(arg1, arg2, callback) {
	var my_number = arg1+arg2;
//Do anything you want to do with the arguments
	if (my_number < 20 ) {
		callback(my_number + 1 );
	} else {
		//callback(my_number);
		return 1;	}
}

As an exercise, execute the above code with different values of num1/num2 and observe the various output scenarios. Note: The last parameter of a function is a callback function and it is defined as an argument.

For C programmers, this may come as a surprise, but this is the way callbacks are. In numerous languages the arguments of a function are always one of the data-types and never a function. However in JavaScript this is not the case.

When we take a look into live examples say for example a DNS client written purely in NodeJS “https://github.com/tjfontaine/node-dns” , the sample code for the client has been provided as is and it is our task to integrate this as a function within our code. We first define a function dns_ query(dns, util, domain_name, ns_ip, record_type ,DNS_cb) where DNS_cb is the callback function.

The example code provided in the node-dns github site:

Integrated code into a function

function dns_query(dns, util, domain_name, ns_ip, record_type ,DNS_cb)
{
var dns_response = '';
	var question = dns.Question({
		name: domain_name,
		type: record_type,
	});
	var req = dns.Request({
		question: question,
		server: { address: ns_ip, port: 53, type: 'udp' },
		timeout: 1000,
	});
	req.on('timeout', function () {
		dns_response = 'Timeout';
		DNS_cb(dns_response);
	});
	req.on('message', function (err, answer) {
		dns_response = answer;
		DNS_cb(dns_response);
	});
	req.on('end', function () {
	});
	req.send();
}

Compare the two codes and observe that wherever we wanted to receive the actual response we have used a callback, whereas the dns_query is called with a few parameters which includes the handle for “dns npm module & util npm module” and the callback function.

var dns = require('dns');
util = require('util');

dns_query(dns, util, domain, '8.8.8.8',record_type.toUpperCase(),function DNS_cb(result) {
console.log(JSON.stringify(result));
});

NodeJS has NPM modules which have been developed to provide various functionalities and are integrated within your code to make your life rather simple. Either you directly install the required NPM or define it in package.json.

The above mentioned code is just the basics, however as you start coding you will realize the Asynchronous Coding and Callbacks are creating a nightmare of all sorts. One needs to have control over flow the asynchronous aspect of NodeJS and help us in executing the code in a linear manner. There exists some excellent modules which will allow you to do just that. My personal favourite is the async by Caolan and can be found over here “https://github.com/caolan/async“.

The methods which you use for processing may differ in its method of execution and for which various Control-Flow methods have been provided.

1: Series: This is used when you want to execute the tasks one at a time.

2: Parallel: This is used when we have to execute all the tasks in parallel.

3: Waterfall: This is used when you need to pass on the results of each task into the next one.

Also when you iterate an array, wherein each and value of the array is processed in a series you may choose to use “eachseries” which is found under “Collections”. Roughly the term “Collections” translates to a data set; in this case it’s an array.

Also note that there are various methods for defining a control-flow function. Some may prefer to define an array containing the function code, yes, you heard it right, an array containing the code. Alternatively, you may directly write the function names / code within async.series(), however it would pose more of a problem while troubleshooting. Also it is interesting to note that the output is in the form of an array.

var async = require('async');
var array = [];
array.push(name1);
array.push(name2);
console.log(array);

//async.series([name1,name2], function (err,results) {
//console.log(results);
//});

async.series(array, function (err,results) {
	console.log('series',results);
	async.parallel(array, function(err,results){
		console.log('parallel',results);
	});
});

function name1(cb) {
	var results = 1;
	cb(null,results);
}

function name2(cb) {
	var results = 2;
	cb(null,results);
}

Our very first example was dealing with arrays. You may use async.series and async.parallel to understand the basic differences, moreover, when we are dealing with databases we need to use this module, as based on the output we have to decide the outcome of the code-execution.

Basic Setup

Enough said, we proceed with the installation and deployment of essential tools for coding in NodeJS.

Download and install the following:

1: NodeJS : http://nodejs.org/download/

2: Eclipse IDE : http://www.nodeclipse.org/updates/

Create a new project in Eclipse Studio and modify the package.json . This file contains the NPM you would want to use and app.js is the file which contains the code.

In order to ensure that all the requisite NPM modules are installed as defined in package.json, right click on package.json Run As npm install to install the NPM packages. Alternatively, you may also use the command line.

Those who would want to use the command line should, after installing NodeJS, create a project directory which holds the package.json and then issue the command

“npm install”.

Note: Remember that the last element of the dependencies in package.json is not terminated by a “,”.

Sample package.json

{
  "name": "Test",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.2.6",
    "mongodb": "1.3.19",
    "monk": "0.7.1",
    "native-dns": "*",
    "jsonlint": "*",
    "async":"*",
    "stream":"*",
    "node-fs":"*",
    "request": "*"
  }
}

From the command line “node app.js” will execute the application you have created. Much of the documentation has been provided on nodejs.org and numerous other sites.

NodeJS is relatively easy once you have understood JavaScript, and those who are migrating from other languages like C , C++ will have to put in extra effort to understand the flexibility of JavaScript and the Asynchronous concept which JavaScript provides. You may always turn to sites like w3schools and stackoverflow to learn about the various JavaScript functions, methods and tricks to over come problems while coding in NodeJS.

When I started working on NodeJS , there were numerous hurdles that I had to overcome, and this article aims to culminate the solutions which were used. There are a few other aspects of NodeJS viz, command-line tools/apps created in NodeJS, databases, webserver and file I/O haven’t been discussed in here.

Quick Reference Links

NodeJS: http://nodejs.org/download/

Eclipse IDE: http://www.nodeclipse.org/updates/

DNS: https://github.com/tjfontaine/node-dns

Control Flow: https://nodejsmodules.org/tags/flow

Documentation: http://nodejs.org/api/

Online Help: http://howtonode.org/ , http://book.mixu.net/node/