(This blog is a collaborative effort of two amazing coders Arijit and Alok. They have penned down their experiences while lately working on Node.js project in the worklab.)
Over the time, we have been working on Node.Js and we learnt a lot about the good and the bad of Node.js and their async nature. We will be sharing the same to help others grasp Node.js and their functional features better –
Node.js is a powerful JavaScript-based framework/platform built on Chrome’s JavaScript V8 Engine. It is a free and open source cross platform used by thousands of developers around the world. It was developed by Ryan Dahl in 2009 and its latest stable version is v5.4.0.
Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, It’s perfect for data-intensive real-time applications that run across distributed devices. It also provides a rich library of various JavaScript modules which simplifies the development of web applications using Node.js to a great extent. Yet, something that makes Node.js a little puzzling for the developers is its async nature.
Most of the developers like us who are using node.js have faced problem with async nature of node at least once in their life. As per general rules, we expect that a function that has been called first will be executed first and the one that’s been called later will follow it up. But the case is not the same with node.js. Yet, it is popular and we continue to use node.js in most of our work. Now you might be thinking why? Let’s try to answer the ‘why’ for our readers…!!
A callback function is a function that:
Once its parent function completes, the function passes as an argument and then called.
For example, a function to read a file may start reading it and return the control to the execution environment immediately so that the next instruction can be executed. Once file I/O operation is completed, it will call the callback function which passes in the parameter of the main/parent function. So there is no blocking. You do not need to wait for the File I/O. This makes Node.js highly scalable, as it can process a high number of requests without waiting for any function to return results.
Blocking Code Example: Create a text file named input.txt with the following content:
Node.js is a powerful JavaScript-based framework/platform built on Chrome’s JavaScript V8 Engine!!!
Create a js file named main.js with the following code:
var fs = require("fs"); var data = fs.readFileSync('input.txt'); console.log(data.toString()); console.log("Program Ended");
Now run the main.js to see the result:
$ node main.js
Verify the Output.
Node.js is a powerful JavaScript-based framework/platform built on Chrome’s JavaScript V8 Engine!!!
Program Ended
Non-Blocking Code Example: Create a text file named input.txt with the following content.
Node.js is a powerful JavaScript-based framework/platform built on Chrome’s JavaScript V8 Engine!!!
Update main.js to have the following code:
var fs = require("fs"); fs.readFile('input.txt', function (err, data) { if (err) return console.error(err); console.log(data.toString()); }); console.log("Program Ended");
Now run the main.js to see the result:
$ node main.js
Verify the Output.
Program Ended
Node.js is a powerful JavaScript-based framework/platform built on Chrome’s JavaScript V8 Engine!!!
These two examples explain the concept of blocking and non-blocking calls.
Thus, a blocking program executes everything in much sequence. From the programming point of view, it is easier to implement the logic, but non-blocking programs fails to execute sequentially. In case a program needs to use any data to be processed, it should be kept within the same block to make it sequential execution.
1. Async nature reduces the execution time, as the code is executed in a non-blocking manner. Refer to the above non-blocking code where while the app is busy reading the file its other functionalities continue to execute
2. Callbacks makes the flow controllable.
var fs = require('fs'); var copyFile = function(source, destination, next) { // we should read source file first fs.readFile(source, function(err, data) { if (err) return next(err); // error occurred // now we can write data to destination file fs.writeFile(destination, data, next); }); };
3. Node even has a feature of event loop which is one of the reasons why Node.js is pretty fast compared to other similar technologies.
1.Most of the callback code ends like this:
fs.readdir(source, function(err, files) { if (err) { console.log('Error finding files: ' + err) } else { files.forEach(function(filename, fileIndex) { console.log(filename) gm(source + filename).size(function(err, values) { if (err) { console.log('Error identifying file size: ' + err) } else { console.log(filename + ' : ' + values) aspect = (values.width / values.height) widths.forEach(function(width, widthIndex) { height = Math.round(width / aspect) console.log('resizing ' + filename + 'to ' + height + 'x' + height) this.resize(width, height).write(destination + 'w' + width + '_' + filename, function(err) { if (err) console.log('Error writing file: ' + err) }) }.bind(this)) } }) }) } });
Henceforth many people call it “PYRAMID OF DOOM”…!!
2.We need to write extra codes to handle the errors.
Now I will leave you to decide whether this async nature of Node.js is a Boon or a Bane. Your queries are welcomed and if you want to know more about Node continue following our blog, we will again get back to you soon with some new stuff.