Frequently asked - Node JS Interview Questions and Answers - Part 03
41. What happens if we call require()
method to load same module multiple times in Node.js
In Node.js, modules are cached after the first time they are loaded. It means every call to the require('module')
will return the same object it cached, if it would resolve to the same file.
That is, caching is based on the actual file name that gets resolved. This is because, in general, there can be different versions of the same package that are installed at different levels of the file hierarchy and that must be loaded accordingly.
42. What are the popular REPL commands in Node.js
REPL stands for Read-Eval-Print-Loop. It is a quick and easy way to test simple Node.js/JavaScript code.
REPL can run pretty much any valid Node.js/JavaScript expression. For example, 10 + 20
in REPL, results in 30
.
The following special commands are supported by all REPL instances:
.break
- When in the process of inputting a multi-line expression, entering the .break command (or pressing the <ctrl>-C key combination) will abort further input or processing of that expression..clear
- Resets the REPLcontext
to an empty object and clears any multi-line expression currently being input..exit
- Close the I/O stream, causing the REPL to exit..help
- Show this list of special commands..save
- Save the current REPL session to a file:> .save ./file/to/save.js
.load
- Load a file into the current REPL session.> .load ./file/to/load.js
.editor
- Enter editor mode (<ctrl>-D to finish, <ctrl>-C to cancel).
43. What is NPM in Node.js
npm
, short for Node Package Manager, is two things: first and foremost, it is an online repository for the publishing of open-source Node.js projects; second, it is a command-line utility for interacting with said repository that aids in package installation, version management, and dependency management.
A package in Node.js contains all the files we need for a module. Modules are JavaScript libraries you can include in your project.
npm consists of three distinct components:
- The website - Use the website to discover packages, set up profiles, and manage other aspects of our npm experience. For example, we can set up Orgs (organizations) to manage access to public or private packages.
- The Command Line Interface (CLI) - The CLI runs from a terminal. This is how most developers interact with npm.
- The registry - The registry is a large public database of JavaScript software and the meta-information surrounding it.
44. Why Node.js application is scalable
Node.js usually scales a bit better then most other typical platforms because of it’s event-based model.
Node’s cluster
module not only provides an out-of-the-box solution to utilizing the full CPU power of a machine, but it also helps with increasing the availability of our Node processes and provides an option to restart the whole application with a zero downtime.
There are mainly three different things we can do to scale an application:
- Cloning - The easiest thing to do to scale a big application is to clone it multiple times and have each cloned instance handle part of the workload. Node.js has the built-in module,
cluster
, to make it easier for us to implement the cloning strategy on a single server. - Decomposing - We can also scale an application by decomposing it based on functionalities and services. This means having multiple, different applications with different code bases and sometimes with their own dedicated databases and User Interfaces. This strategy is commonly associated with the term Microservice, where micro indicates that those services should be as small as possible, but in reality, the size of the service is not what’s important but rather the enforcement of loose coupling and high cohesion between services.
- Splitting - We can also split the application into multiple instances where each instance is responsible for only a part of the application’s data. This strategy is often named horizontal partitioning, or sharding, in databases.
45. How will you debug an application in Node.js
There are many ways to debug our application in Node.js. One of the most common form of debugging is the use of console.log statement. But it will not be helpful in most of the time. There are other ways:
- Node inspector is a powerful JavaScript debugger for NodeJS applciations that uses the blink developer tools. It has many advanced features like, navigate in your source files; set breakpoints; step over, step in, step out, resume; hover your mouse over an expression in your source to display its value in a tooltip and lot more. To start debugging, we should run
node-debug app.js
. - Visual Studio code Node.js debugger communicates to the Node.js runtimes through wire protocols, the set of supported runtimes is determined by all runtimes supporting the wire protocols.
46. How will you convert a Buffer to JSON in Node.js
Nodejs and browser based JavaScript differ because Node has a way to handle binary data even before the ES6 draft came up with ArrayBuffer. In Node, Buffer
class is the primary data structure used with most I/O operations. It is a raw binary data that is allocated outside the V8 heap and once allocated, cannot be resized.
Buffers can be converted into JSON as follow.
let bufferOne = Buffer.from('This is a buffer example.');
console.log(bufferOne);
// Output: <Buffer 54 68 69 73 20 69 73 20 61 20 62 75 66 66 65 72 20 65 78 61 6d 70 6c 65 2e>
let json = JSON.stringify(bufferOne);
console.log(json);
// Output: {"type": "Buffer", "data": [84,104,105,115,32,105,115,32,97,32,98,117,102,102,101,114,32,101,120,97,109,112,108,101,46]}
To convert a JSON into Buffer:
let bufferOriginal = Buffer.from(JSON.parse(json).data);
console.log(bufferOriginal);
// Output: <Buffer 54 68 69 73 20 69 73 20 61 20 62 75 66 66 65 72 20 65 78 61 6d 70 6c 65 2e>
47. Why do we use __filename
in Node.js
The __filename
is one of the Global objects in Node.js and represents the filename of the code being executed. This is the resolved absolute path of this code file.
Based on the location of your program, it will return the file name as follows:
//main.js
console.log( __filename );
/web/com/1427091028_21099/main.js
Node.js also has another Global object to get the name of the directory that the currently executing script resides in called __dirname
.
48. What is the use of Timers is Node.js
The Timers module in Node.js contains functions that execute code after a set period of time. Timers do not need to be imported via require()
, since all the methods are available globally to emulate the browser JavaScript API.
The Node.js API provides several ways of scheduling code to execute at some point after the present moment. The functions below may seem familiar, since they are available in most browsers, but Node.js actually provides its own implementation of these methods.
Node.js Timer provides setTimeout()
, setImmediate()
and setInterval
.
49. What are the important APIs in Timers module in Node.js
The Timers API are as follows:
setTimeout
- setTimeout()
can be used to schedule code execution after a designated amount of milliseconds. This function is similar to window.setTimeout()
from the browser JavaScript API, however a string of code cannot be passed to be executed. setTimeout()
accepts a function to execute as its first argument and the millisecond delay defined as a number as the second argument. Additional arguments may also be included and these will be passed on to the function.
function welcome(name) {
console.log("Hello " + name);
}
setTimeout(welcome, 1500, 'World!');
The above function myFunc()
will execute as close to 1500 milliseconds (or 1.5 seconds) as possible due to the call of setTimeout()
.
setImmediate
- setImmediate()
will execute code at the end of the current event loop cycle. This code will execute after any I/O operations in the current event loop and before any timers scheduled for the next event loop. This code execution could be thought of as happening “right after this”, meaning any code following the setImmediate()
function call will execute before the setImmediate()
function argument.
console.log('before immediate');
setImmediate((arg) => {
console.log("executing immediate: " + arg);
}, 'in setImmediate');
console.log('after immediate');
// before immediate
// after immediate
// executing immediate: so immediate
setInterval
- If there is a block of code that should execute multiple times, setInterval()
can be used to execute that code. setInterval()
takes a function argument that will run an infinite number of times with a given millisecond delay as the second argument.
function intervalFunc() {
console.log('Cant stop me now!');
}
setInterval(intervalFunc, 1500);
setTimeout()
, setImmediate()
, and setInterval()
return a timer object that can be used to reference the set Timeout
or Immediate
object. By passing said object into the respective clear function, execution of that object will be halted completely. The respective functions are clearTimeout()
, clearImmediate()
, and clearInterval()
.
50. What is the use of net.Socket in Node.js
A net.Socket
can be created by the user and used directly to interact with a server. For example, it is returned by net.createConnection(), so the user can use it to talk to the server.
It can also be created by Node.js and passed to the user when a connection is received. For example, it is passed to the listeners of a ‘connection’ event emitted on a net.Server
, so the user can use it to interact with the client.
51. What are the important events of net.Socket
in Node.js
The net
module provides an asynchronous network API for creating stream-based TCP or IPC servers and clients.
net.Socket
is an abstraction of a TCP socket or a streaming IPC endpoint. A net.Socket
is also a duplex stream, so it can be both readable and writable, and it is also an EventEmitter
.
Some of the events are:
- close: Emitted once the socket is fully closed. The argument
hadError
is a boolean which says if the socket was closed due to a transmission error. - connect - Emitted when a socket connection is successfully established.
- data - Emitted when data is received. The argument data will be a
Buffer
orString
. - drain - Emitted when the write buffer becomes empty. It can be used to throttle uploads.
- end - Emitted when the other end of the socket sends a FIN packet, thus ending the readable side of the socket.
- error - Emitted when an error occurs. The ‘
close
’ event will be called directly following this event. - lookup - Emitted after resolving the hostname but before connecting. It is not applicable to UNIX sockets.
- ready - Emitted when a socket is ready to be used.
- timeout - Emitted if the socket times out from inactivity. This is only to notify that the socket has been idle.
52. Can we build a REST service in Node.js
Yes, we can. In a server, routing refers to determining how an application responds to a client request for a specific endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on). Below we have defined two basic routes(/tasks
, and /tasks/taskId
) with different methods.
‘/tasks’ has to methods(GET
and POST
), while /tasks/taskId
has GET, PUT and DELETE.
'use strict';
module.exports = function(app) {
// todoList Routes
app.route('/tasks')
.get(/* get method response */)
.post(/* delete method response */);
app.route('/tasks/:taskId')
.get(/* get method response */)
.put(/* put method response */)
.delete(/* delete method response */);
};
53. What is the use of DNS module in Node.js
dns
module which provide underlying system’s name resolution and DNS look up facilities. DNS module consists of an asynchronous network wrapper.
The most commonly used functions in DNS module are:
dns.lookup(adress, options, callback)
- The dns lookup method takes any website address as its first parameter and returns the corresponding first IPV4 or IPV6 record. The options parameter can be an integer or object. If no options are provided both IPV4 and IPV6 are valid inputs. The third parameter is the callback functions.dns.lookupservice(address, port, callback)
- This function converts any physical address such as “www.knowledgehills.com” to array of record types. The record types are specified by the second parameter “rrbyte”. Finally the third method is the callback function.dns.getServers()
- This function returns an array of IP address strings, formatted according to rfc5952, that are currently configured for DNS resolution. A string will include a port section if a custom port is used.dns.setServers()
- This function sets the IP address and port of servers to be used when performing DNS resolution. Thedns.setServers()
method must not be called while a DNS query is in progress.
54. What are the important command line options in Node.js
Some of the most used Node.js CLI options are:
- —version or -v - Using the
node --version
, or short,node -v
, we can print the version of Node.js we are using. - —eval or -e - Using the
--eval
option, we can run JavaScript code right from your terminal. The modules which are predefined in REPL can also be used without requiring them, like thehttp
or thefs
module. - —inspect[=host:port] - Using node
--inspect
will activate the inspector on the provided host and port. If they are not provided, the default is127.0.0.1:9229
. The debugging tools attached to Node.js instances communicate via a tcp port using the Chrome Debugging Protocol. - —zero-fill-buffers - Node.js can be started using the
--zero-fill-buffers
command line option to force all newly allocated Buffer instances to be automatically zero-filled upon creation. The reason to do so is that newly allocated Buffer instances can contain sensitive data. - —check or -c - The
--check
option instructs Node.js to check the syntax of the provided file, without actually executing it. - —prof-process - Using the
--prof-process
, the Node.js process will output the v8 profiler output.
55. How does Node.js work
Node is single threaded and all Node JS applications uses “Single Threaded Event Loop Model” architecture to handle multiple concurrent clients. But actually it is event-driven and single-threaded with background workers. The main event loop is single-threaded but most of the I/O works run on separate threads, because the I/O APIs in Node.js are asynchronous/non-blocking by design, in order to accommodate the event loop.
Event loop allows Node.js to perform non-blocking I/O operation, despite the fact that JavaScript is single-threaded and by offloads operations to the system kernel whenever possible. This event loop has following phases:
timers
: this phase executes callbacks scheduled bysetTimeout()
andsetInterval()
. A timer specifies the threshold after which a provided callback may be executed rather than the exact time a person wants it to be executed.- I/O callbacks: executes almost all callbacks with the exception of close callbacks, the ones scheduled by timers, and
setImmediate()
. - idle and prepare: only used internally.
- poll: retrieve new I/O events; node will block here when appropriate.
- check: setImmediate() callbacks are invoked here.
- close callbacks: e.g.
socket.on('close', ...)
. Here every phase follows FIFO stack like queue mechanism to handle callbacks. Each phase is unique , generally, when the event loop enters a given phase, it will perform any operations specific to that phase, then execute callbacks in that phase’s queue until the queue has been exhausted or the maximum number of callbacks has executed. When the queue has been exhausted or the callback limit is reached, the event loop will move to the next phase, and so on.
56. How do you resolve unhandled exceptions in a Node.js program
In a production system it is really important to capture uncaught exceptions too. E.g. a simple type conversion is missing, or a file is write protected, then our application stop working and we don’t know why. Or our Application restart automatically and we don’t see any error.
In Node.js an uncaughtException event is fired. We can capture that event with a simple:
process.on("uncaughtException", function(err) { ... });
57. What is a Callback function in Node.js
Node.js, being an asynchronous platform, doesn’t wait around for things like file I/O to finish - Node.js uses callbacks. A callback is a function called at the completion of a given task; this prevents any blocking, and allows other code to be run in the meantime.
function processData (callback) {
fetchData(function (err, data) {
if (err) {
console.log("An error has occured. Abort everything!");
callback(err);
}
data += 1;
callback(data);
});
}
Callbacks are the foundation of Node.js. Callbacks give us an interface with which to say, “and when you’re done doing that, do all this.” This allows us to have as many IO operations as our OS can handle happening at the same time. For example, in a web server with hundreds or thousands of pending requests with multiple blocking queries, performing the blocking queries asynchronously gives you the ability to be able to continue working and not just sit still and wait until the blocking operations come back.
58. What is the use of QueryString in Node.js
The Node.js Query String provides methods to deal with query string. It can be used to convert query string into JSON object and vice-versa.
To use query string module, we need to use require('querystring')
.
The querystring.parse()
method parses a URL query string (str
) into a collection of key and value pairs. For example, the query string 'foo=bar&abc=xyz&abc=123'
is parsed into:
{
foo: 'bar',
abc: ['xyz', '123']
}
The object returned by the querystring.parse()
method does not prototypically inherit from the JavaScript Object. This means that typical Object
methods such as obj.toString()
, obj.hasOwnProperty()
, and others are not defined and will not work.
59. How will you get the amount of free memory on the server in which Node.js application is running
The built-in process
module has a method memoryUsage
that offers insight in the memory usage of the current Node.js process.
The process.memoryUsage()
method returns an object describing the memory usage of the Node.js process measured in bytes. For example, the code:
console.log(process.memoryUsage());
Will generate:
{
rss: 4935680,
heapTotal: 1826816,
heapUsed: 650472,
external: 49879
}
heapTotal
and heapUsed
refer to V8’s memory usage. external
refers to the memory usage of C++ objects bound to JavaScript objects managed by V8. rss
, Resident Set Size, is the amount of space occupied in the main memory device (that is a subset of the total allocated memory) for the process, which includes the heap, code segment and stack.
The heap is where objects, strings, and closures are stored. Variables are stored in the stack and the actual JavaScript code resides in the code segment.
60. What are the security mechanisms available in Node.js
We can secure our Node.js application in the following ways:
Authentication - Authentication is one of the primary security stages at which user is identified as permitted to access the application at all. Authentication verifies the user’s identity through one or several checks. In Node.js, authentication can be either session-based or token-based. In session-based authentication, the user’s credentials are compared to the user account stored on the server and, in the event of successful validation, a session is started for the user. Whenever the session expires, the user needs to log in again. In token-based authentication, the user’s credentials are applied to generate a string called a token which is then associated with the user’s requests to the server.
Error Handling - Usually, the error message contains the explanation of what’s actually gone wrong for the user to understand the reason. At the same time, when the error is related to the application code syntax, it can be set to display the entire log content on the frontend. For an experienced hacker, the log content can reveal a lot of sensitive internal information about the application code structure and tools used within the software.
Request Validation - Another aspect which has to be considered, while building a secure Node.js application, is a validation of requests or, in other words, a check of the incoming data for possible inconsistencies. It may seem that invalid requests do not directly affect the security of a Node.js application, however, they may influence its performance and robustness. Validating the incoming data types and formats and rejecting requests not conforming to the set rules can be an additional measure of securing your Node.js application.
Node.js Security Tools and Best Practices - We can use tools like helmet (protects our application by setting HTTP headers), csurf (validates tokens in incoming requests and rejects the invalid ones), node rate limiter (controls the rate of repeated requests. This function can protect you from brute force attacks) and cors (enables cross-origin resource sharing).
61. What is promise-all in node.js
promise-all is a node module for tracking down promise states of all promise functions executing in parallel. Similar to promise.all function, but it rejects the complete promise.all()
even if any one of the promise fails, where as promises-all npm will indiviudally return you the states. Below is an example:
var PromiseAll = require('promises-all');
PromiseAll.all([promise1, promise2]).then(function(response) {
console.log(response);
}, function(error) {
console.log(error);
});
Will output:
{
resolve: [ /* promise resolved */ ],
reject: [ / * prmoise rejected */ ]
}
62. How can we secure cookies in Node.js
We can follow below steps to secure our cookies:
- HttpOnly - HttpOnly is a flag that can be included in a Set-Cookie response header. The presence of this flag will tell browsers to not allow client side script access to the cookie (if the browser supports it). This is important because it helps protect our cookie data from malicious scripts and helps mitigate the most common XSS attacks.
- Secure - Equally important as the HttpOnly flag is the Secure flag. This too is included in a Set-Cookie response header. The presence of the secure flag tells web browsers to only send this cookie in requests going to HTTPS endpoints. This is very important, as the cookie information will not be sent on an unencrypted channel. This helps mitigate some exploits where your browser is redirected to the HTTP endpoint for a site rather than the HTTPS endpoint and thus potentially exposing your cookies to someone in the middle of the traffic.
63. What is the passport in Node.js
Passport.js is a simple, unobtrusive Node.js authentication middleware for Node.js. Passport.js can be dropped into any Express.js-based web application.
Passport recognizes that each application has unique authentication requirements. Authentication mechanisms, known as strategies, are packaged as individual modules. Applications can choose which strategies to employ, without creating unnecessary dependencies.
By default, if authentication fails, Passport will respond with a 401 Unauthorized
status, and any additional route handlers will not be invoked. If authentication succeeds, the next
handler will be invoked and the req.user property will be set to the authenticated user.
64. What is the meaning of tilde and caret in package.json
In the simplest terms, the tilde matches the most recent minor version (the middle number). ~1.2.3 will match all 1.2.x versions but will miss 1.3.0.
The caret, on the other hand, is more relaxed. It will update to the most recent major version (the first number). ^1.2.3 will match any 1.x.x release including 1.3.0, but will hold off on 2.0.0.
65. How can we control versioning about packages in Node.js
If we are using a version of npm prior to 5 then we can use npm shrinkwrap
. This locks down the versions of the npm modules we are currently using. Once committed to the project if anybody else npm install they get the exact versions specified in shrink wrap.
With the release of npm 5 it automatically creates an package-lock.json
file, similar to shrinkwrap, when we run npm install by default. We should commit the lock or shinkwrap files.
We can also look into Yarn. Yarn comes out of the box with a yarn.lock
file which works in the same way but with additional performance speeds and offline capabilities.
66. Difference between dependencies and dev dependencies
dependencies
are required and crucial to run our application, devDependencies
are required only for development, e.g.: unit tests, ES6 to Javascript transpilation, minification.
In development this doesn’t matter because regular npm install
installs both sets of dependencies anyway, but if NODE_ENV
is set to production npm will skip devDependencies
. We can also explicitly choose what we want to install using the --only
option:
npm install --only=prod[uction]
installs onlydependencies
npm install --only=dev[elopment]
installs onlydevDependencies
Let’s say that we’re using a continuous deployment service. If we setNODE_ENV
to production andwebpack
is listed underdevDependencies
(like in many codebases I have seen), the build will fail because webpack won’t get installed. We can always test if we divided the dependencies correctly by installing them with the option --only=prod
.