in Development

Your Basic NodeJS Know-How

1

For this article we hit up one of our web developer friends, Alex, to get a little bit of information about how NodeJS works and provide you with a fully functional example as well as a step-by-step walkthrough to get you started.

Being born in 2009, NodeJS is a relatively new runtime environment that developers can use in order to create server-side and networking applications. NodeJS uses the Google V8 JavaScript engine in order to execute code, the exact same engine that is powering Google Chrome with great success and proven reliability.

A NodeJS server actually runs in a loop. A loop always ready to accept and respond to requests. Any of the requests may initiate a chain of other requests or signal an action to the server such as reading database records and sending them via response to the user. In addition to this, it natively supports event-driven IO, making it the perfect choice for creating all types of real-time web applications.

Basic Syntax

To demonstrate how easy it is to create a server, consider the following code (file server.js):

var http = require('http'); // Require the http module (native NodeJS module)
 
var ourServer = http.createServer(function (req, res) {
 
res.writeHead(200, {'Content-Type': 'text/plain'});
 
res.end('Ah, my gorgeous server \n');
 
});
 
ourServer.listen(1234, '127.0.0.1');
 
console.log(“Server running at http://127.0.0.1:1234/ or http://localhost:1234”);

The example can be run by opening a terminal window, going to the directory in which server.js is located and typing “node server.js”. Open a browser window and go to http://127.0.0.1:1234/ or http://localhost:1234/ to visit the webpage.

Let’s go through what actually happens:

At first, we ask for the built-in http module in order to access the protocol’s features. This call will return an object containing the “createServer” method used to define the server behaviour.

By calling the “createServer” method, we have to implement a callback function which will define our server’s behavior. Note that our function has two parameters “req” (the request object) and “res” (the response object). Both objects contain methods which we can use to manipulate every request sent to the server and every response that we will send. Another thing to note is that the “createServer” method returns a WebServer object.

The “listen” method is called on the WebServer object and actually starts our server, supplying it with two parameters: the port and the host we will use.

All that remains to be done is to log our server’s birth by using the console module, simply calling console.log(message).

Let’s complicate things a bit

We see how easy it is to define a server and its interactions with the requests and responses. The tricky part comes when we actually need to implement complex logic in our application.

Let’s say, for instance, that each request sends us a parameter via “GET”, named “myNumber”. If myNumber is odd, we have to return a list with the IP and timestamp of all the previous requests which received an odd parameter, same thing if “myNumber” is even.

 

var http = require('http'); // Require the http module (native NodeJS module)
 
 
 
var previousOddRequests = [];
 
var previousEvenRequests = [];
 
 
 
var ourServer = http.createServer(function (req, res) {
 
 
 
var parsedRequest = require('url').parse(req.url, true);
 
var myNumber = parsedRequest.query.myNumber;
 
 
 
if (typeof myNumber === 'undefined')
 
return false;
 
 
 
var currentRequest = {
 
host : req.headers.host,
 
time : new Date().toString(),
 
number : myNumber
 
};
 
 
 
if (myNumber % 2 == 0) {
 
previousEvenRequests.push(currentRequest);
 
res.writeHead(200, {'Content-Type': 'text/plain'});
 
res.end(JSON.stringify(previousEvenRequests) + '\n');
 
} else {
 
previousOddRequests.push(currentRequest);
 
res.writeHead(200, {'Content-Type': 'text/plain'});
 
res.end(JSON.stringify(previousOddRequests) + '\n');
 
}
 
 
 
});
 
ourServer.listen(1234, '127.0.0.1');
 
console.log(“Server running at http://127.0.0.1:1234/ or http://localhost:1234”);
 
console.log(“Requests format : http://127.0.0.1:1234?myNumber=NumberValue”);

Save the file as server2.js and run it as the previous example. Use one of the following links to test our server’s logic:

http://127.0.0.1:1234/?myNumber=12 or http://127.0.0.1:1234/?myNumber=23.

Notice how the code is becoming more complicated to maintain, and taking into consideration the fact that in the future we will introduce various changes and improvements to our server, the code may easily reach 400-500 lines in a single file.

Avoiding such monster files is rather simple by using modules. Think of a module as the smallest part which will be integrated in a much larger system with the purpose of solving one problem and that problem only. The previous being said, the application becomes the fusion point of all its modules, being easy to debug and much easier to extend.

Your first module

Node modules are located in the “node_modules” directory of your web application, more exactly, consider the following structure:

App directory

server.js

node_modules (directory)

myModule (directory)

package.json

myModule.js

The package.json file is needed for your module to be compatible with the node package management tool (npm). It is a JSON formatted file, filled with information about how your node will be handled, as well as author data, etc.

{ “name” : “myModule”,

“main” : “myModule.js” }

The myModule.js file will contain the actual module logic, which will be exported into the application.

 

var myModule = function() {
 
 
 
var previousOddRequests = [];
 
var previousEvenRequests = [];
 
 
 
this.parseRequest = function(request, response) {
 
var parsedRequest = require('url').parse(request.url, true);
 
var myNumber = parsedRequest.query.myNumber;
 
 
 
if (typeof myNumber === 'undefined')
 
return false;
 
 
 
var currentRequest = {
 
host : request.connection.remoteAddresso,
 
time : new Date().toString(),
 
number : myNumber
 
};
 
 
 
if (myNumber % 2 == 0) {
 
previousEvenRequests.push(currentRequest);
 
response.writeHead(200, {'Content-Type': 'text/plain'});
 
response.end(JSON.stringify(previousEvenRequests) + '\n');
 
} else {
 
previousOddRequests.push(currentRequest);
 
response.writeHead(200, {'Content-Type': 'text/plain'});
 
response.end(JSON.stringify(previousOddRequests) + '\n');
 
}
 
}
 
}

 

module.exports = new myModule();

Integrating the module into your application

Integrating the module is the easiest part, require the module using the name supplied in the “package.json” file.

By calling require, node will check the module.exports field of the required module thus, in our case, returning a new instance of the myModule class.

Conclusion

Maintaining and extending complex applications may not be an easy thing due to the large codebase involved. Modular design is a way to ease the stress of maintaining (every feature is independent, making it easy to create test suites for each functionality) and updating your application (due to the fact that a module can simply be replaced by another).

One more thing to note: “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” (Rick Osborne)

Anamaria

I read, I write, I sleep.

Leave a Reply