Node.js Important questions and answers
Q. How does Node.js work?
Node.js is completely event-driven. Basically, the server consists of one thread processing one event after another.
A new request coming in is one kind of event. The server starts processing it and when there is a blocking IO operation, it does not wait until it completes and instead registers a callback function. The server then immediately starts to process another event ( maybe another request ). When the IO operation is finished, that is another kind of event, and the server will process it ( i.e. continue working on the request ) by executing the callback as soon as it has time.
Node.js Platform does not follow the Request/Response Multi-Threaded Stateless Model. It follows Single Threaded with Event Loop Model. Node.js Processing model mainly based on Javascript Event-based model with Javascript callback mechanism.
Single Threaded Event Loop Model Processing Steps:
- Clients Send requests to the Web Server.
- Node.js Web Server internally maintains a Limited Thread pool to provide services to the Client Requests.
- Node.js Web Server receives those requests and places them into a Queue. It is known as Event Queue.
- Node.js Web Server internally has a Component, known as Event Loop. Why it got this name is that it uses an indefinite loop to receive requests and process them.
- Event Loop uses Single Thread only. It is the main heart of the Node.js Platform Processing Model.
- Event Loop checks any Client Request is placed in the Event Queue. If no, then wait for incoming requests indefinitely.
- If yes, then pick up one Client Request from Event Queue
- Starts to process that Client's Request
- If that Client Request Does Not require any Blocking IO Operations, then process everything, prepare a response and send it back to the client.
- If that Client Request requires some Blocking IO Operations like interacting with Database, File Systems, and External Services then it will follow a different approach
- Checks Threads availability from Internal Thread Pool
- Picks up one Thread and assign this Client Request to that thread.
- That Thread is responsible for taking that request, processing it, performing Blocking IO operations, preparing a response, and sending it back to the Event Loop
- Event Loop, in turn, sends that Response to the respective Client.
Q. What are the core modules of Node.js?
Node.js has a set of core modules that are part of the platform and come with the Node.js installation. These modules can be loaded into the program by using the required function.
Syntax:
const module = require('module_name');
Example:
const http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('Welcome to Node.js!');
res.end();
}).listen(3000);
The following table lists some of the important core modules in Node.js.
Core Module | Description |
---|---|
assert - | provides a set of assertion functions useful for testing |
console - | provides a simple debugging console |
crypto - | provides cryptographic functionality |
HTTP - | HTTP module includes classes, methods, and events to create a Node.js HTTP server. |
URL - | URL module includes methods for URL resolution and parsing. |
query string - | querystring module includes methods to deal with a query strings. |
path - | path module includes methods to deal with file paths. |
fs - | fs module includes classes, methods, and events to work with file I/O. |
util - | util module includes utility functions useful for programmers. |
Q. What do you understand by Reactor Pattern in Node.js?
A reactor Pattern is used to avoid the blocking of the Input/Output operations. It provides us with a handler that is associated with I/O operations. When the I/O requests are to be generated, they get submitted to a demultiplexer, which handles concurrency in avoiding the blocking of the I/O mode and collects the requests in form of an event and queues those events.
There are two ways in which I/O operations are performed:
1. Blocking I/O: The application will make a function call and pause its execution at a point until the data is received. It is called "Synchronous".
2. Non-Blocking I/O: The application will make a function call, and, without waiting for the results it continues its execution. It is called "Asynchronous".
Reactor Pattern comprises of:
1. Resources: They are shared by multiple applications for I/O operations, generally slower in executions.
2. Synchronous Event De-multiplexer/Event Notifier: This uses Event Loop for blocking on all resources. When a set of I/O operations completes, the Event De-multiplexer pushes the new events into the Event Queue.
3. Event Loop and Event Queue: Event Queue queues up the new events that occurred along with its event-handler, pair.
4. Request Handler/Application: This is, generally, the application that provides the handler to be executed for registered events on resources.
Q. What are the global objects of node.js?
Node.js Global Objects are the objects that are available in all modules. Global Objects are built-in objects that are part of JavaScript and can be used directly in the application without importing any particular module.
These objects are modules, functions, strings, and the object themselves as explained below.
1. global:
It is a global namespace. Defining a variable within this namespace makes it globally accessible.
var myvar;
2. process:
It is an inbuilt global object that is an instance of EventEmitter used to get information on the current process. It can also be accessed using require() explicitly.
3. console:
It is an inbuilt global object used to print to stdout and stderr.
console.log("Hello World"); // Hello World
4. setTimeout() ,clearTimeout(), setInterval(), clearInterval():
The built-in timer functions are global
function printHello() {
console.log( "Hello, World!");
}
// Now call above function after 2 seconds
var timeoutObj = setTimeout(printHello, 2000);
5. __dirname:
It is a string. It specifies the name of the directory that currently contains the code.
console.log(__dirname);
6. __filename:
It specifies the filename of the code being executed. This is the resolved absolute path of this code file. The value inside a module is the path to that module file.
console.log(__filename);
Q. What is setTimeout() functions?
setTimeout() -
SetTimeout function executes the code after the specified /given time. The method executes the code only once.
Another way: Sometimes we need our code gets executed after some time, in this situation we use this function.
Syntax: setTimeout(function, milliseconds);
setTimeout(() => {
console.log("Delayed for 1 second.");
}, 1000)
//Prints the
Delayed for 1 second
Q. What is a chrome v8 engine?
V8 is a C++-based open-source JavaScript engine developed by Google. It was originally designed for Google Chrome and Chromium-based browsers ( such as Brave ) in 2008, but it was later utilized to create Node.js for server-side coding.
V8 is the JavaScript engine i.e. it parses and executes JavaScript code. The DOM and the other Web Platform APIs ( they all makeup runtime environments) are provided by the browser.
V8 is known to be a JavaScript engine because it takes JavaScript code and executes it while browsing in Chrome. It provides a runtime environment for the execution of JavaScript code. The best part is that the JavaScript engine is completely independent of the browser in which it runs.
Q. Why is LIBUV needed in Node JS?
libuv is a C library originally written for Node.js to abstract non-blocking I/O operations. It provide the below features
- It allows the CPU and other resources to be used simultaneously while still performing I/O operations, thereby resulting in efficient use of resources and network.
- It facilitates an event-driven approach wherein I/O and other activities are performed using callback-based notifications.
- It provides mechanisms to handle file system, DNS, network, child processes, pipes, signal handling, polling and streaming
- It also includes a thread pool for offloading work for some things that can't be done asynchronously at the operating system level.
Q. How V8 compiles JavaScript code?
Compilation is the process of converting human-readable code to machine code. There are two ways to compile the code
- Using an Interpreter: The interpreter scans the code line by line and converts it into byte code.
- Using a Compiler: The Compiler scans the entire document and compiles it into highly optimized byte code.
The V8 engine uses both a compiler and an interpreter and follows just-in-time (JIT) compilation to speed up the execution. JIT compiling works by compiling small portions of code that are just about to be executed. This prevents long compilation time and the code being compiles is only that which is highly likely to run.
Q. What is EventEmitter in Node.js?
The EventEmitter is a class that facilitates communication/interaction between objects in Node.js. The EventEmitter class can be used to create and handle custom events.
EventEmitter is at the core of Node asynchronous event-driven architecture. Many of Node's built-in modules inherit from EventEmitter including prominent frameworks like Express.js. An emitter object basically has two main features:
- Emitting name events.
- Registering and unregistering listener functions.
Example 01: Create an event emitter instance and register a couple of callbacks
/**
* Callbacks Events
*/
const events = require('events');
const eventEmitter = new events.EventEmitter();
function listenerOne() {
console.log('First Listener Executed');
}
function listenerTwo() {
console.log('Second Listener Executed');
}
eventEmitter.on('listenerOne', listenerOne); // Register for listenerOne
eventEmitter.on('listenerOne', listenerTwo); // Register for listenerOne
// When the event "listenerOne" is emitted, both the above callbacks should be invoked.
eventEmitter.emit('listenerOne');
// Output
First Listener Executed
Second Listener Executed
Example 02: Registering for the event to be fired only one time using once.
/**
* Emit Events Once
*/
const events = require('events');
const eventEmitter = new events.EventEmitter();
function listenerOnce() {
console.log('listenerOnce fired once');
}
eventEmitter.once('listenerOne', listenerOnce); // Register listenerOnce
eventEmitter.emit('listenerOne');
// Output
listenerOnce fired once
Example 03: Registering for the event with callback parameters
/**
* Callback Events with Parameters
*/
const events = require('events');
const eventEmitter = new events.EventEmitter();
function listener(code, msg) {
console.log(`status ${code} and ${msg}`);
}
eventEmitter.on('status', listener); // Register listener
eventEmitter.emit('status', 200, 'ok');
// Output
status 200 and ok
Q. How the Event Loop Works in Node.js?
The event loop allows Node.js to perform non-blocking I/O operations despite the fact that JavaScript is single-threaded. It is done by offloading operations to the system kernel whenever possible.
Node.js is a single-threaded application, but it can support concurrency via the concept of event and callbacks. Every API of Node.js is asynchronous and being single-threaded, they use async function calls to maintain concurrency. Node uses observer pattern. Node thread keeps an event loop and whenever a task gets completed, it fires the corresponding event which signals the event-listener function to execute.
Features of Event Loop:
- Event loop is an endless loop, which waits for tasks, executes them and then sleeps until it receives more tasks.
- The event loop executes tasks from the event queue only when the call stack is empty i.e. there is no ongoing task.
- The event loop allows us to use callbacks and promises.
- The event loop executes the tasks starting from the oldest first.
Example:
/**
* Event loop in Node.js
*/
const events = require('events');
const eventEmitter = new events.EventEmitter();
// Create an event handler as follows
const connectHandler = function connected() {
console.log('connection succesful.');
eventEmitter.emit('data_received');
}
// Bind the connection event with the handler
eventEmitter.on('connection', connectHandler);
// Bind the data_received event with the anonymous function
eventEmitter.on('data_received', function() {
console.log('data received succesfully.');
});
// Fire the connection event
eventEmitter.emit('connection');
console.log("Program Ended.");
// Output
Connection succesful.
Data received succesfully.
Program Ended.
Q. What is the difference between process.nextTick() and setImmediate()?
1. process.nextTick():
As we know Event loop is keep running ,So when the Event loop complete the one cycle is known as Tick.
The process.nextTick() method adds the callback function to the start of the next event queue tick. ie. Once we are called the process.nextTick() so its does not wait for empty the stack and process the request, Its immediately start process the task by the event loops.
It is to be noted that, at the start of the program process.nextTick() method is called for the first time before the event loop is processed.
process.nextTick() run before the setImmdeiate and setTimeout() function.
2. setImmdeiate():
The setImmediate() method is used to execute a function right after the current event loop finishes. It is callback function is placed in the check phase of the next event queue.
Example:
/**
* setImmediate() and process.nextTick()
*/
setImmediate(() => {
console.log("1st Immediate");
});
setImmediate(() => {
console.log("2nd Immediate");
});
process.nextTick(() => {
console.log("1st Process");
});
process.nextTick(() => {
console.log("2nd Process");
});
// First event queue ends here
console.log("Program Started");
// Output
Program Started
1st Process
2nd Process
1st Immediate
2nd Immediate
Q. What is callback function in Node.js?
A callback is a function which is called when a task is completed, thus helps in preventing any kind of blocking and a callback function allows other code to run in the meantime.
Callback is called when task get completed and is asynchronous equivalent for a function. Using Callback concept, Node.js can process a large number of requests without waiting for any function to return the result which makes Node.js highly scalable.
Example:
/**
* Callback Function
*/
function myAsync(a, b, callback) {
setTimeout(function () {
callback(a + b);
}, 100);
}
console.log("Before Asynchronous Call");
myAsync(10, 20, function (result) {
console.log("Sum: " + result);
});
console.log("After Asynchronous Call");
// Output
Before Asynchronous Call
After Asynchronous Call
Sum: 30
Q. What are the difference between Events and Callbacks?
1. Events:
Node.js events module which emits named events that can cause corresponding functions or callbacks to be called. Functions ( callbacks ) listen or subscribe to a particular event to occur and when that event triggers, all the callbacks subscribed to that event are fired one by one in order to which they were registered.
All objects that emit events are instances of the EventEmitter class. The event can be emitted or listen to an event with the help of EventEmitter
Example:
/**
* Events Module
*/
const event = require('events');
const eventEmitter = new event.EventEmitter();
// add listener function for Sum event
eventEmitter.on('Sum', function(num1, num2) {
console.log('Total: ' + (num1 + num2));
});
// call event
eventEmitter.emit('Sum', 10, 20);
// Output
Total: 30
2. Callbacks:
A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.
Example:
/**
* Callbacks
*/
function sum(number) {
console.log('Total: ' + number);
}
function calculator(num1, num2, callback) {
let total = num1 + num2;
callback(total);
}
calculator(10, 20, sum);
// Output
Total: 30
Callback functions are called when an asynchronous function returns its result, whereas event handling works on the observer pattern. The functions that listen to events act as Observers. Whenever an event gets fired, its listener function starts executing. Node.js has multiple in-built events available through events module and EventEmitter class which are used to bind events and event-listeners
Q. What is an error-first callback?
The pattern used across all the asynchronous methods in Node.js is called Error-first Callback. Here is an example:
fs.readFile( "file.json", function ( err, data ) {
if ( err ) {
console.error( err );
}
console.log( data );
});
Any asynchronous method expects one of the arguments to be a callback. The full callback argument list depends on the caller method, but the first argument is always an error object or null. When we go for the asynchronous method, an exception thrown during function execution cannot be detected in a try/catch statement. The event happens after the JavaScript engine leaves the try block.
In the preceding example, if any exception is thrown during the reading of the file, it lands on the callback function as the first and mandatory parameter.
Q. What is callback hell in Node.js?
Callback hell
is a phenomenon that afflicts a JavaScript developer when he tries to execute multiple asynchronous operations one after the other.
An asynchronous function is one where some external activity must complete before a result can be processed; it is “asynchronous” in the sense that there is an unpredictable amount of time before a result becomes available. Such functions require a callback function to handle errors and process the result.
getData(function(a){
getMoreData(a, function(b){
getMoreData(b, function(c){
getMoreData(c, function(d){
getMoreData(d, function(e){
...
});
});
});
});
});
Techniques for avoiding callback hell:
- Using Async.js
- Using Promises
- Using Async-Await
- Managing callbacks using Async.js
Async
is a really powerful npm module for managing asynchronous nature of JavaScript. Along with Node.js, it also works for JavaScript written for browsers.
Async provides lots of powerful utilities to work with asynchronous processes under different scenarios.
npm install --save async
- ASYNC WATERFALL
var async = require('async');
async.waterfall([
function(callback) {
//doSomething
callback(null, paramx); //paramx will be availaible as the first parameter to the next function
/**
The 1st parameter passed in callback.
@null or @undefined or @false control moves to the next function
in the array
if @true or @string the control is immediately moved
to the final callback function
rest of the functions in the array
would not be executed
*/
},
function(arg1, callback) {
//doSomething else
// arg1 now equals paramx
callback(null, result);
},
function(arg1, callback) {
//do More
// arg1 now equals result
callback(null, 'done');
},
function(arg1, callback) {
//even more
// arg1 now equals 'done'
callback(null, 'done');
}
], function (err, result) {
//final callback function
//finally do something when all function are done.
// result now equals 'done'
});
- ASYNC SERIES
var async = require('async');
async.series([
function(callback){
// do some stuff ...
callback(null, 'one');
/**
The 1st parameter passed in callback.
@null or @undefined or @false control moves to the next function
in the array
if @true or @string the control is immedeatly moved
to the final callback function with the value of err same as
passed over here and
rest of the functions in the array
would not be executed
*/
},
function(callback){
// do some more stuff ...
callback(null, 'two');
}
],
// optional callback
function(err, results){
// results is now equal to ['one', 'two']
});
- Managing callbacks hell using promises
Promises are alternative to callbacks while dealing with asynchronous code. Promises return the value of the result or an error exception. The core of the promises is the .then()
function, which waits for the promise object to be returned. The .then()
function takes two optional functions as arguments and depending on the state of the promise only one will ever be called. The first function is called when the promise if fulfilled (A successful result). The second function is called when the promise is rejected.
var outputPromise = getInputPromise().then(function (input) {
//handle success
}, function (error) {
//handle error
});
- Using Async Await
Async await makes asynchronous code look like it\’s synchronous. This has only been possible because of the reintroduction of promises into node.js. Async-Await only works with functions that return a promise.
const getrandomnumber = function(){
return new Promise((resolve, reject)=>{
setTimeout(() => {
resolve(Math.floor(Math.random() * 20));
}, 1000);
});
}
const addRandomNumber = async function(){
const sum = await getrandomnumber() + await getrandomnumber();
console.log(sum);
}
addRandomNumber();
Q. What is typically the first argument passed to a Node.js callback handler?
The first argument to any callback handler is an optional error object
function callback(err, results) {
// usually we'll check for the error before handling results
if(err) {
// handle error somehow and return
}
// no error, perform standard callback handling
}
0 Comments