Node.js is an asynchronous, event-driven, non-blocking I/O application. It is built with a V8 engine along with other node core components like Libuv. Libuv library developed in C++ provides event loop mechanism and I/O API for concurrent operations. Thanks to this multithreading language which helps in handling concurrent tasks. This mechanism makes Node.js an asynchronous event-based platform in which everything is a reaction to an event.
Above diagram gives a glimpse of how Node.Js works and will use it to understand the event loop better. Node.js is a single thread application and all the blocking calls are stored in the call stack and once they are processed they are removed from the call stack. Let's take an example:
When we run a node, line 1 is moved to call stack and executed and then followed up by line 2 and then line 3. A similar thing can be observed if an error is raised then from the error stack, we can know the order of execution.
Node.js provides timer functions globally. We can work with Node.js asynchronously is through using the timing functions. The timing functions setTimeout, clearTimeout, setInterval, and clearInterval work the same way they do in the browser and are available to you globally.
So whenever asynchronous calls are observed during execution, those are moved to API block and the call stack is continued. When the asynchronous operation is done say setTimeout, the execution of call-backs is done by the event loop i.e. it moved the callback of setTimeout to Event Queue. And event loop will be keeping monitoring the call stack to get empty. And once it is empty then call back is pushed to call stack and executed.
Note: Libuv library basically creates a thread pool to offload the asynchronous work. If the operating system provides an interface for I/O tasks then this is used instead of working with threads.
Below are the examples of global timer functions:
App1: Simple example using setTimeout with a callback to log in console.
var waitTime = 3000; console.log(“wait for it”);
setTimeout(() => console.log(“done”), waitTime);
App2: Extending above example with usage of setInterval along wit
var waitTime = 3000; var currentTime = 0; var waitInterval = 500; console.log(“wait for it”); setTimeout(() => console.log(“done”), waitTime);
var waitTime = 3000; var currentTime = 0; var waitInterval = 500; console.log(“wait for it”); setInterval(() => { currentTime =+ waitInterval; console.log(`waiting ${currentTime/1000} seconds…`); // to display in seconds }, waitInterval); setTimeout(() => console.log(“done”), waitTime);
var waitTime = 3000; var currentTime = 0; var waitInterval = 500; console.log(“wait for it”); var interval = setInterval(() => { currentTime =+ waitInterval; console.log(`waiting ${currentTime/1000} seconds…`); }, waitInterval); setTimeout(() => { clearInterval(interval); console.log(“done”) }, waitTime);
App3:
Let's modify this code to display the time waiting in a percentage and also control the standard output, so that we overwrite the last line, meaning that we can see a percentage number grow.
function writeWaitingPercent(percent) { process.stdout.clearLine(); // clears the previous line process.stdout.cursorTo(0); // moves the cursor to first line process.stdout.write(`waiting ... ${percent}%`); // add the text to first line }
setTimeout(() => { clearInterval(interval); writeWaitingPercent(100); console.log(“done”) }, waitTime);
var interval = setInterval(() => { currentTime =+ waitInterval; percentWaited = Math.floor((currentTime/waitTime) * 100); writeWaitingPercent(percentWaited); }, waitInterval);
varwaitTime = 3000; varcurrentTime = 0; varwaitInterval = 500; varpercentWaited = 0; functionwriteWaitingPercent(percent) { process.stdout.clearLine(); process.stdout.cursorTo(0); process.stdout.write(`waiting ... ${percent}%`); } varinterval = setInterval(function() { currentTime += waitInterval; percentWaited = Math.floor((currentTime/waitTime) * 100); writeWaitingPercent(percentWaited); }, waitInterval); setTimeout(function() { clearInterval(interval); writeWaitingPercent(100); console.log("\n\n done \n\n"); }, waitTime); writeWaitingPercent(percentWaited);
Output:
node timers waiting ... 100% done
EventEmitter is another core module which comes along with Node.js. It helps in build a pub sub pattern i.e. to emit and listen to custom events. Lets use this module and understand with the help of an example.
App1:
App2:
One other important about these events is that they are asynchronous and raised when they happen. Let take another example.
const input = data.toString().trim(); emitter.emit(“customEvent”, input, “terminal”); });
const input = data.toString().trim(); if (input === ‘exit’) { emitter.emit(“customEvent”, “user has exited”, “terminal”); process.exit(); } emitter.emit(“customEvent”, input, “terminal”); });
App3:
Let's create an object and add event handling mechanism to that object with the help of eventEmitter.
this.name = name; }
console.log(`${this.name}`: ${msg}); });
varEventEmitter = require('events').EventEmitter; varutil = require('util'); varPerson = function(name) { this.name = name; }; util.inherits(Person, EventEmitter); varemployee = newPerson("SomePerson"); employee.on('programmer', function(msg) { console.log(`${this.name}: ${msg}`); }); employee.emit('programmer', "You are a good learner.");
Output:
SomePerson: You are a good learner.
JavaScript is a dynamic computer programming language for the web. Jav...
Introduction: Angular (What is Angular?)Angular was formerly introdu...
Leave a Reply
Your email address will not be published. Required fields are marked *