Node.js Basics

In this article I will write about how to start developing applications with Node.js with some simples examples. These examples are very simple, they are only supposed to show the basic concepts and not to be view as production ready code. The idea is to keep it simple.

 

What is Node.js?

In the official Node.js site is written:

“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.”

 

Installation / Pre-Requisites

To run Node.js in ours machines we need to install Node.js and NPM (Node Package Manager).

The installation process is very simple, at least in Ubuntu, only need to run one simple command. Homebrew also allows for one line install on MacOS .

sudo apt-get install nodejs nodejs-legacy npm

Note: nodejs-legacy contains a symlink for legacy Node.js.

And you will need to have basic knowledge of programming and Javascript.

 

1. First Example: Hello World!

Of course, the first example could only be Hello World!

To do this we need to create a file called “1_helloworld.js” and write:

console.log("Hello World!");

The function ‘console.log’ is very familiar for Web Developers,  especially for Javascript Script developers.

Now we will run our first application. To run Node.js applications is quite simple: node “file name”. To run this example we only need to write in terminal:

$ node 1_helloworld.js
Hello World!

As you can see, is very easy to create this simple application, only one line of code, no need to import any library, it’s really straightforward!  Let’s complicate a little in next examples.

 

2. Command line arguments

In this example we will show the number of arguments and the values of arguments.

Create a file called “2_arguments.js” and write this code:

console.log('\nNumber of arguments: ' + process.argv.length + '\n');
process.argv.forEach(function(value, index) {
	console.log('Parameter [' + index + ']: ' + value);
});

To test this example run this command on terminal:

$ node 2_arguments.js Bytencode Rules!
Number of parameters: 4
Parameter [0]: node
Parameter [1]: /home/user/nodejs-basics/2_arguments.js
Parameter [2]: Bytencode
Parameter [3]: Rules!

Note: The list of arguments always includes all strings of the executed command.

 

3. First App: Operations with numbers

Using the knowledge of the previous examples, we will create our first application. The app will receive three arguments: two numbers and one operator. The goal is apply the operator on that numbers, calculate and show the result. To simplify the operator can only be: +, -, :, x.

Create a file named ’3_numbers_operation.js’ and write this code:

if(process.argv.length != 5) {
	console.log("Invalid number of parameters!");
	process.exit(1);
}
var num1 = parseInt(process.argv[2]);
var operator = process.argv[3];
var num2 = parseInt(process.argv[4]);
var result;
switch(operator){
	case "+": result = num1 + num2; break;
	case "-": result = num1 - num2; break;
	case "x": result = num1 * num2; break;
	case ":": result = num1 / num2; break;
	default:
		console.log("Invalid operator!");
		process.exit(2);
}
console.log( num1 + ' ' + operator + ' ' + num2 + ' = ' + result );

Notes:

- process.exit(n): End process with ‘failure’ code n (n>0);

- parseInt: Parses a string and returns an integer.

To try this app do the following command:

$ node 3_numbers_operation.js 12 x 9
12 x 9 = 108

Try others operators and numbers.

 

4. Create a Module

In Node.js is possible to create our own modules with several routines and they can be reused by other applications.

In this example we will create one module with two functions that reuse the code of last example ‘Operations with numbers’.

Create a file that represents the module and call it ‘number_operation_md.js’ with the following code:

module.exports = {
   calculate: function (number1, operator, number2) {
       var result;
       switch(operator){
           case "+": result = number1 + number2; break;
           case "-": result = number1 - number2; break;
           case "x": result = number1 * number2; break;
           case ":": result = number1 / number2; break;
           default:
               console.log("Invalid operator!");
               result = 0;
       }
	return result;
   	},
   	print: function (number1, operator, number2, result) {
    	console.log( number1 + ' ' + operator + ' ' + number2 + ' = ' + result );
   	}
}

Note: To simplify this example, if the operator is invalid the result is zero.

Create the main file app named ’4_modules.js’ and put this code:

var mymodule = require("./number_operation_md.js");
if(process.argv.length != 5) {
	console.log("Invalid number of parameters!");
	process.exit();
}
var num1 = parseInt(process.argv[2]);
var operator = process.argv[3];
var num2 = parseInt(process.argv[4]);
var result = mymodule.calculate(num1, operator, num2);
mymodule.print(num1, operator, num2, result);

Note: To load a module you need to call the function ‘require’ and pass in the filename.

To test the app run the following code:

$ node 4_modules.js
5 : 2 = 2.5

 

4.1. Using internal module

Node.js provides multiple modules that we can use in our application. I will give one example to show how to use them.

In the previously created module ‘number_operation_md.js’, we printed the result like this:

console.log( number1 + ' ' + operator + ' ' + number2 + ' = ' + result );

If we wanted to change the code to something more ‘correct’, like a printf in C, we can use  the  Node.js module ‘util’ and the function ‘format’, getting something like this:

console.log(util.format('%d %s %d = %d', number1, operator, number2, result));

To use this in our module we also need to add one line of code to load ‘util’ module:

var util = require('util');

 

5. File Handling: Write

For handling files we will need to load ‘fs’ (file system) module. In this module all methods have two ways functions of operation: synchronous and asynchronous. The sync mode will be blocked until the file operation is over, while async mode will not block your app.

In the first file handling example we will write a text message in synchronous mode.

Create the file  ’5_file_write.js’ and put the code:

var fs = require('fs');
fs.writeFileSync('file_sync.txt', 'Byte&Code Rules!!');
console.log('The \'File file_sync.txt\' is saved!');

Running the app:

$ node 5_file_write.js
The 'File file_sync.txt' is saved!

After running this app it will create the ‘file temp_file_sync.txt’ with text:

$ cat temp_file_sync.txt

Byte&Code Rules!!
The sample example but written in async modes:

var message = 'Hello Byte&Code!';
fs.writeFile('file_async.txt', message, function (error) {
	if (error) throw error;
	console.log('The \'File file_async.txt\' is saved!');
});

Note: The last parameter of function ‘writeFile’ is a callback function, that is called when the file operation is over.

If you want, for example, to create a simple log file you can use the function ‘appendFile’. Example:

var message = new Date().toISOString() + ' > Byte&Code Developing Great Ideas!';
fs.appendFile('file.log', '\n' + message, function (err) {
	if (err) throw err;
	console.log('The \'' + message + '\' was appended to file file.log!');
});

Notes:

- new Date().toISOString() returns a string using the ISO standard

- Every time you run the code will added the message to the end of file.

 

6. File Handling: Read

To read a file in async mode you have the function ‘readFile’.

Create a file ’6_file_read.js’ and put the code:

var fs = require('fs');
fs.readFile('file_async.txt', function (err, content) {
	if (err) throw err;
  	console.log('File Content [file_async.txt]:\n' + content + '\n');
});

To read file on sync mode add this code in the end:

var fileContent = fs.readFileSync('file_sync.txt');
console.log('File Content [file_sync.txt]:\n' + fileContent + '\n');

Running this app on terminal:

$ node 6_file_read.js
File Content [file_sync.txt]:
Byte&Code Rules!!
File Content [file_async.txt]:
Hello Byte&Code!

Note: As you can see the first message is for sync operation and then comes message for async, but the code is in reverse order.

 

7. Read Directory Contents

To read the contents of a directory in async mode we have the function ‘readdir’ and for sync mode exist the function ‘readdirSync’.

In this example the app will take one argument which is a path of the directory and then show the contents.

Create a file ’7_list_dir_content.js’ with the folling code:

var fs = require('fs');
fs.readdir(process.argv[2], function (error, dirContent) {
	dirContent.forEach(function (file) {
		console.log(file);
	});
});

Running this app on terminal:

$ node 7_list_dir_content.js /usr/
X11R6
bin
games
include
lib
lib32
local
sbin
share
src

 

8. Create a simple configuration file

We can create a configuration file using a module file. To do this create a file named ’8_config_file.js’ and add this code:

var config = {
	host : 'www.bytencode.com',
	port : 80
}
module.exports = config;

On main app file ’8_config_app.js’ write this code:

var appConfig = require('./config_file.js');
console.log("config.host: " + appConfig.host);
console.log("config.port: " + appConfig.port);

Running this app on terminal:

$ node 8_config_app.js
config.host: www.bytencode.com
config.port: 80

 

9. Create Web Server

In this topic we will create some Web Servers.

To create a webserver we will need to load node module ‘http’.

 

9.1. Simple Web Server

First we will create a Web Server that return a plain text.

Create a file ’9_simple_webserver_text.js’ and add the following code:

var http = require('http');
var server = http.createServer(function (req, res) {
	res.writeHead(200, {'Content-Type': 'text/plain'});
	res.end('Byte&Code Rules!!');
});
server.listen(8888);

To run the server run this command:

$ node 9_simple_webserver_text.js

At this time the server is running on port 8888. Open your browser and point it to this URL http://localhost:8888.

Your browser will show: “Byte&Code Rules!!”.

 

9.2. Web Server: Get query string parameters

Now we will create a web server that will use query string parameters from URL. For that we need to load the ‘url’ module to have URL utilities (resolution and parsing).

In this example the app will take 3 parameters (operator and two numbers). The goal is equal to ‘Operations with numbers’, apply the operator on that numbers, calculate and show the result, but in this case we will use query string parameters. To reuse code we will use the module ‘number_operation_md.js’.
Create file ’9_query_string.js’ and add this code:

var http = require('http');
var url = require("url");
var util = require('util');
var mymodule = require("./number_operation_md.js");
var server = http.createServer(function (req, res) {
	var params = url.parse(req.url, true).query;
	var output;
	if(Object.keys(params).length != 3)
		output = "Invalid number of parameters!";
	else {
		var num1 = parseInt(params['num1']);
		var operator = params['operator'];
		var num2 = parseInt(params['num2']);
		var result = mymodule.calculate(num1, operator, num2);
		output = util.format('%d %s %d = %d', num1, operator, num2, result);
	}
	res.writeHead(200, {'Content-Type': 'text/plain'});
	res.end(output);
});
server.listen(8888);

Start the server with this command:

$ node 9_query_string.js

Open your browser and point it to this URL http://localhost:8888 and it will show “Invalid number of parameters!”. Change URL to http://localhost:8888/?num1=10&operator=x&num2=25 and it will show “10 x 25 = 250”.

 

9.3. Get a binary and save the file

This example will show how to download a image from a site and save it on file system.

This app will download a image located here and save it as ‘bytencode.png’.

Create file ’9_download_binary.js’ and put the following code:

var http = require('http');
var fs = require('fs');
var request = http.get("http://www.bytencode.com/img/cube_big.png", function(response){
	response.setEncoding('binary')
   	var binaryBuffer = '';
   	response.on('data', function(chunk){
    	binaryBuffer += chunk
	});
   	response.on('end', function(){
    	fs.writeFile('bytencode.png', binaryBuffer, 'binary', function(err){
        	if (err) throw err
           	console.log('File bytencode.png saved.')
       	});
   	});
});

Run the app:

$ node 9_download_binary.js
File bytencode.png saved.

 

9.4. Web Server: Return a binary

This example will show how to return a image on a Web Server. We will use the file ‘bytencode.png’ downloaded on previous example.
Create file ’9_upload_binary.js’ and put the following code:

var http = require('http');
var fs = require('fs')
var server = http.createServer(function (req, res) {
	fs.readFile("bytencode.png", "binary", function(error, fileContent) {
	    if(error) {
			res.writeHead(500, {"Content-Type": "text/plain"});
			res.write(error);
			res.end();
			return;
		}
		res.writeHead(200);
		res.write(fileContent, "binary");
		res.end();
	});
});
server.listen(8888);

Open your browser and put this URL http://localhost:8888 and it will show the file ‘bytencode.png’.

 

9.5. Web Server – Create a static site

For this example we will need some html and css files for the site. You can download this files here (bytencode.html e bytencode.html) and put it in the same folder of the app.
Create  ’9_static_site.js’ a put this code:

var server = http.createServer(function(req, res) {
	var filename = req.url == '/' ? 'bytencode.html' : req.url.substring(1);
	console.log("File Requested: " + filename);
	fs.readFile(filename, "binary", function(error, fileContent) {
		if(error) {
		res.writeHead(404, {"Content-Type": "text/plain"});
		res.end('404 Not Found');
		return;
		}
		res.writeHead(200);
		res.write(fileContent, "binary");
		res.end();
	});
});
server.listen(8888);

Note: This code will only redirect the request to the specified file. If the URL does not specify the file, the code will redirect to ‘bytencode.html’ (default page).

Open the browser with this URL http://localhost:8888 and it will show the site. If you add a specified file on URL you will get the file. Example: http://localhost:8888/bytencode.png

Attention: If you put http://localhost:8888/9_static_site.js the server will send the content of your code. To solve this problem you can create a folder called ‘public’ and put all html, css, images and other resource on it, and keep you code files in a separed path that the server does not publish.

 

9.6. Web Server: Create REST API  / JSON

In this example the web server will have two endpoints to get some system info:

- System Info: http://localhost:8888/api/system

- System Date: http://localhost:8888/api/date

We will need to load the ‘os’ module to get some system info.

Create ’9_system_info_api.js’ file and put the following code:

var http = require('http');
var os = require('os');
function getSystemInfo(){
	return  {
		tmpdir: os.tmpdir(),
		endianness: os.endianness(),
		hostname: os.hostname(),
		type: os.type(),
		platform: os.platform(),
		arch: os.arch(),
		release: os.release(),
		uptime: os.uptime(),
		loadavg: os.loadavg(),
		totalmem: os.totalmem(),
		freemem: os.freemem(),
		cpus: os.cpus(),
		networkInterfaces: os.networkInterfaces(),
		EOL: os.EOL
	};
}
function getDate(){
	var date = new Date();
	return {
		date: date.toISOString()
	};
}
var server = http.createServer(function (req, res) {
	var content;
	if (/^\/api\/system/.test(req.url))
	    content = getSystemInfo();
	else if (/^\/api\/date/.test(req.url))
		content = getDate();
	if(content) {
	    res.writeHead(200, { 'Content-Type': 'application/json' })
	    res.end(JSON.stringify(content))
	}
	else {
	    res.writeHead(404, {"Content-Type": "text/plain"});
		res.end('404 Not Found');
	}
});
server.listen(8888);

Open the browser and put these URLs http://localhost:8888/api/system and http://localhost:8888/api/date

 

Conclusion

This is the end of this article about Node.js. I will return with more articles about Node.js, deepening some of the topics, creating some examples and applications with well-known modules like mongodb and express, and others useful modules.

I hope you enjoyed.

Feel free to comment.

Here are some useful links:

- Official Node.js site: http://nodejs.org/

- Internal Node Modules documentation: http://nodejs.org/api/

- Community Node Modules: https://nodejsmodules.org/

Leave a Comment.