Node.js Interview Questions and Answers
Practice Node.js interview questions from fundamentals through production architecture, including the event loop, asynchronous I/O, modules, streams, workers, testing, performance, and modern runtime APIs.
This topic combines the source question bank with current corrections and newly added questions for modern APIs and production practices. Version-specific details should still be checked against official documentation when preparing for a real interview.
Entry questions
1 questions- Question 1Entry
What npm is used for?
- Node.js
Reveal answerHide answer
npm stands for Node Package Manager. npm provides the following two main functionalities: Online repositories for Node.js packages/modules which are searchable on search.nodejs.org Command-line utility to install packages, do version management and dependency management of Node.js packages. Another important use for npm is dependency management. When you have a node project with a package.json file, you can run npm install from the project root and npm will install all the dependencies listed in the package.json.
Junior questions
15 questions- Question 2Junior
What is libuv ?
- Node.js
Reveal answerHide answer
libuv is a C library that is used to abstract non-blocking I/O operations to a consistent interface across all supported platforms. 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.
- Question 3Junior
Why we always require modules at the top of a file? Can we require modules inside of functions?
- Node.js
Reveal answerHide answer
Yes. CommonJS require() can be called inside a function, and Node caches a module after it is loaded. Top-level dependencies are usually easier to discover and fail earlier during startup, but lazy loading can be appropriate for optional or expensive dependencies and rare code paths. In ES modules, static import declarations stay at module scope; use dynamic import() when runtime loading is required.
- Question 4Junior
What's the difference between process.cwd() vs __dirname ?
- Node.js
Reveal answerHide answer
process.cwd() returns the process's current working directory, which depends on where or how the process was started and can be changed with process.chdir(). __dirname is a CommonJS module variable containing the directory of the current module file, so it does not change with the process working directory. In ES modules, __dirname is not provided; modern Node.js exposes import.meta.dirname, and import.meta.url can also be used when supporting older ESM versions.
- Question 5Junior
What does Promisifying technique mean in Node.js?
- Node.js
Reveal answerHide answer
This technique is a way to be able to use a classic Javascript function that takes a callback, and have it return a promise: For example:
const fs = require('fs') const getFile = (fileName) => { return new Promise((resolve, reject) => { fs.readFile(fileName, (err, data) => { if (err) { reject(err)return
} resolve(data) }) }) } getFile('/etc/passwd') .then(data => console.log(data)) .catch(err => console.log(err)) - Question 6Junior
Name some Built-in Globals in Node.js
- Node.js
Reveal answerHide answer
Node.js has a number of built-in global identifiers that every Node.js developer should have some familiarity with. Some of these are true globals, being visible everywhere; others exist at the module level, but are inherent to every module, thus being pseudo-globals. The list of true globals: global - The global namespace. Setting a property to this namespace makes it globally visible within the running process. process - The Node.js built-in process module, which provides interaction with the current Node.js process. Read More console - The Node.js built-in console module, which wraps various STDIO functionality in a browser-like way. Read More setTimeout() , clearTimeout() , setInterval() , clearInterval() - The built-in timer functions are globals. Read More The pseudo-globals included at the module level in every module: module , module.exports , exports - These objects all pertain to the Node.js module system. Read More __filename - The __filename keyword contains the path of the currently executing file. Note that this is not defined while running the Node.js REPL. __dirname - Like __filename , the __dirname keyword contains the path to the root directory of the currently executing script. Also not present in the Node.js REPL. require() - The require() function is a built-in function, exposed per-module, that allows other valid modules to be included.
- Question 7Junior
What is the file package.json ?
- Node.js
Reveal answerHide answer
All npm packages contain a file, usually in the project root, called package.json - this file holds various metadata
{ "name" : "barebones", "version" : "0.0.0", } - Question 8Junior
What is the difference between returning a callback and justcalling a callback?
- Node.js
Reveal answerHide answer
return callback();
//some more lines of code; - won't be executed callback(); //some more lines of code; - will be executedOf course returning will help the context calling async function get the value returned by callback.
function do2(callback) { log.trace('Execute function: do2'); return callback('do2 callback param'); } var do2Result = do2((param) => { log.trace(`print ${param}`); return `return from callback(${param})`; // we could use that return }); log.trace(`print ${do2Result}`);Output:
C:\Work\Node>node --use-strict main.js [0] Execute function: do2 [0] print do2 callback param [0] print return from callback(do2 callback param) - Question 9Junior
What do you mean by Asynchronous API?
- Node.js
Reveal answerHide answer
An asynchronous API lets work complete later without blocking JavaScript while it waits. Node.js provides many asynchronous APIs for I/O, but not every Node.js API is asynchronous: synchronous variants such as fs.readFileSync() also exist. Async operations may be handled by the operating system, libuv, or the libuv thread pool, and completion is delivered through callbacks, promises, or events.
- Question 10Junior
What is V8?
- Node.js
Reveal answerHide answer
The V8 library provides Node.js with a JavaScript engine (a program that converts Javascript code into lower level or machine code that microprocessors can understand), which Node.js controls via the V8 C++ API. V8 is maintained by Google, for use in Chrome. The Chrome V8 engine : The V8 engine is written in C++ and used in Chrome and Nodejs. It implements ECMAScript as specified in ECMA-262. The V8 engine can run standalone we can embed it with our own C++ program.
- Question 11Junior
What is Callback Hell and what is the main cause of it?
- Node.js JavaScript
Reveal answerHide answer
Asynchronous JavaScript, or JavaScript that uses callbacks, is hard to get right intuitively. A lot of code ends up looking 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(dest + 'w' + width + '_' + filename, function(err) { if (err) console.log('Error writing file: ' + err) }) }.bind(this)) } }) }) } }) See the pyramid shape and all the }) at the end? This is affectionately known as callback hell.The cause of callback hell is when people try to write JavaScript in a way where execution happens visually from top to bottom. Lots of people make this mistake! In other languages like C, Ruby or Python there is the expectation that whatever happens on line 1 will finish before the code on line 2 starts running and so on down the file.
- Question 12Junior
What are the key features of Node.js?
- Node.js
Reveal answerHide answer
Node.js is a JavaScript runtime built on V8 with an event-driven architecture and strong support for non-blocking I/O. JavaScript commonly runs on an event-loop thread, while Node can also use operating-system asynchronous facilities, libuv's worker pool, child processes, and worker_threads. Node supports CommonJS and ES modules, streams with backpressure, built-in web APIs such as fetch(), and a large package ecosystem. It is particularly well suited to network services and I/O-heavy workloads; CPU-heavy JavaScript should be partitioned or moved to workers or processes.
- Question 13Junior
Why does Node.js prefer Error-First Callback?
- Node.js
Reveal answerHide answer
The usual pattern is that the callback is invoked as callback(err, result) , where only one of err and result is non-null, depending on whether the operation succeeded or failed. Without this convention, developers would have to maintain different signatures and APIs, without knowing where to place the error in the arguments array.
fs.readFile(filePath, function(err, data) { if (err) { //handle the error } // use the data object }); - Question 14Junior
What is Callback?
- Node.js
Reveal answerHide answer
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. Callbacks are the foundation of Node.js. Callbacks give you an interface with which to say, "and when you're done doing that, do all this."
var myCallback = function(data) { console.log('got data: '+data); }; var usingItNow = function(callback) { callback('get it?'); }; - Question 15Junior
Explain the difference between local and global npm packages installation
- Node.js
Reveal answerHide answer
The main difference between local and global packages is this: local packages are installed in the directory where you run npm install , and they are put in the node_modules folder under this directory global packages are all put in a single place in your system (exactly where depends on your setup), regardless of where you run npm install -g In general, all packages should be installed locally. This makes sure you can have dozens of applications in your computer, all running a different version of each package if needed. Updating a global package would make all your projects use the new release, and as you can imagine this might cause nightmares in terms of maintenance, as some packages might break compatibility with further dependencies, and so on.
- Question 16Junior
What are the benefits of using Node.js?
- Node.js
Reveal answerHide answer
Following are main benefits of using Node.js Aynchronous and Event Driven - All APIs of Node.js library are aynchronous that is non-blocking. It essentially means a Node.js based server never waits for a API to return data. Server moves to next API after calling it and a notification mechanism of Events of Node.js helps server to get response from the previous API call. Very Fast - Being built on Google Chrome's V8 JavaScript Engine, Node.js library is very fast in code execution. Single Threaded but highly Scalable - Node.js uses a single threaded model with event looping. Event mechanism helps server to respond in a non-bloking ways and makes server highly scalable as opposed to traditional servers which create limited threads to handle requests. Node.js uses a single threaded program and same program can services much larger number of requests than traditional server like Apache HTTP Server. No Buffering - Node.js applications never buffer any data. These applications simply output the data in chunks.
Mid questions
48 questions- Question 17Mid
How would you read files in parallel in Node.js? Provide a code example
- Node.js
Reveal answerHide answer
If you want to read the files in parallel, use map , and you can await the array of promises that you'll get with Promise.all :
async function printFiles () { const files = await getFilePaths(); await Promise.all(files.map(async (file) => { const contents = await fs.readFile(file, 'utf8') console.log(contents) })); } - Question 18Mid
What exactly does module.exports do in Node.js, and what would a simple example be?
- Node.js
Reveal answerHide answer
module.exports is the object that's actually returned as the result of a require call. The exports variable is initially set to that same object (i.e. it's a shorthand "alias"), so in the module code you would usually write something like this:
let myFunc1 = function() { ... }; let myFunc2 = function() { ... }; exports.myFunc1 = myFunc1; exports.myFunc2 = myFunc2;to export (or "expose") the internally scoped functions myFunc1 and myFunc2 . And in the calling code you would use:
const m = require('./mymodule'); m.myFunc1(); where the last line shows how the result of require is (usually) just a plain object whose properties may be accessed. - Question 19Mid
Explain how does Node.js work?
- Node.js
Reveal answerHide answer
A Node.js application creates a single thread on its invocation. Whenever Node.js receives a request, it first completes its processing before moving on to the next request. Node.js works asynchronously by using the event loop and callback functions, to handle multiple requests coming in parallel. An Event Loop is a functionality which handles and processes all your external events and just converts them to a callback function. It invokes all the event handlers at a proper time. Thus, lots of work is done on the back-end, while processing a single request, so that the new incoming request doesn’t have to wait if the processing is not complete.
While processing a request, Node.js attaches a callback function to it and moves it to the back-end. Now, whenever its response is ready, an event is called which triggers the associated callback function to send this response.
- Question 20Mid
What is the meaning of the @ prefix on npm package?
- Node.js
Reveal answerHide answer
This is a new feature of NPM called scoped packages, which effectively allow NPM package to be namespaced. Every user and organization on NPM has their own scope, and they are the only people who can add packages to it. It allows organizations to make it clear which packages are offical and which ones are not. Consider: If a package has the scope @angular , you know it was published by the Angular core team. The package name only has to be unique to the scope it is published in, not the entire registry. For example: The package name http is already taken in the main repository, but Angular is able to have @angular/http as well.
- Question 21Mid
Provide your favourite reasons to use Node.js
- Node.js
Reveal answerHide answer
Reasons to use NodeJS: It runs Javascript, so you can use the same language on server and client, and even share some code between them (e.g. for form validation, or to render views at either end.) The single-threaded event-driven system is fast even when handling lots of requests at once, and also simple, compared to traditional multi-threaded Java or ROR frameworks. The ever-growing pool of packages accessible through NPM, including client and server-side libraries/modules, as well as command-line tools for web development. Most of these are conveniently hosted on github, where sometimes you can report an issue and find it fixed within hours! It's nice to have everything under one roof, with standardised issue reporting and easy forking. It has become the defacto standard environment in which to run Javascript-related tools and other web- related tools, including task runners, minifiers, beautifiers, linters, preprocessors, bundlers and analytics processors. It seems quite suitable for prototyping, agile development and rapid product iteration.
- Question 22Mid
Which one is better: Node.js built in cluster or PM2 clustering?
- Node.js
Reveal answerHide answer
If your application is stateless then it is easy to use pm2 cluster mode as it does not require much effort (or no effort) in code changes. if your application uses local data, sessions or using sockets then it is recommended to use Node.js inbuilt cluster module and start your application normally using pm2.
- Question 23Mid
When would you use cluster module in Node.js?
- Node.js
Reveal answerHide answer
The Node.js cluster module is used with Node.js any time you want to spread out the request processing across multiple node.js processes. This is most often used when you wish to increase your ability to handle more requests/second and you have multiple CPU cores in your server. By default, a single instance of Node.js will not fully utilise multiple cores because the core Javascript you run in your server is single-threaded (uses one core). Clustering also provides you with some additional fault tolerance. If one cluster process goes down, you can still have other live clusters serving requests while the disabled cluster restarts. Because each cluster is a separate process, there is no automatic shared data among the different cluster processes. As such, clustering is simplest to implement either where there is no shared data or where the shared
data is already in a place where it can be accessed by multiple processes (such as in a database).
const http = require('http'); const cluster = require('cluster'); const os = require('os'); const process = require('process'); const express = require('express'); const port = 8000; const numCPUs = os.cpus().length; console.log(`No of cpu = ${numCPUs}`);//Creating child processes from main process based on number of cpus if (cluster.isMaster) { console.log(`Primary ${process.pid} is running`);// Fork workers. for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`worker ${worker.process.pid} died`); cluster.fork(); }); } else { const app = express(); app.get('/', (req, res) => { console.log(`Incoming req accepted by Process ${process.pid}`); for(let i=0; i<9999999999999999999; i++) { } res.send('hello world'); }); app.get('/test', (req, res) => { console.log(`Incoming req accepted by Process ${process.pid}`); res.send('Quickly say Hello World'); }); app.listen(port, () => { console.log(`app is listening at port ${port} by Process ${process.pid}`); }); } - Question 24Mid
What is the purpose of pm2 save ?
- Node.js
Reveal answerHide answer
pm2 save takes a snapshot of your currently running Node applications. You can then restore these applications using pm2 resurrect . This is useful because it means you don't have to manually restart each application when you restart pm2 (such as a machine reboot). Instead, you can just have a script that calls pm2 resurrect and it'll start up all the Node apps. pm2 resurrect is useful to be called manually. If you want your processes to automatically start on boot, you should create a startup script with pm2 startup .
- Question 25Mid
How do I run a Node.js app as a background service?
- Node.js
Reveal answerHide answer
Use some process managers:
Systemd (Linux) Launchd (Mac) node-windows (Windows) PM2 (Node.js) Forever - Question 26Mid
Is an Event Emitter Synchronous or Asynchronous?
- Node.js
Reveal answerHide answer
Events are synchronous and blocking. The events raised by event emitters are synchronously executed by the listeners in the current event loop’s iteration. They are implemented with simple function calls. If you look at the eventEmitter code, to send an event to all listeners, it literally just iterates through an array of listeners and calls each listener callback, one after the other. Consider:
import { EventEmitter } from 'events'; const eventEmitter = new EventEmitter(); eventEmitter.on('myEvent', (data) => { console.log(data); }); console.log('Statement A'); eventEmitter.emit('myEvent', 'Statement B'); console.log("Statement C");When we execute this code snippet, we get the following output in the console:
Statement A Statement B Statement C
- Question 27Mid
What's the Event Loop?
- Node.js
Reveal answerHide answer
The event loop is what allows Node.js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible. Every I/O requires a callback - once they are done they are pushed onto the event loop for execution. Since most modern kernels are multi-threaded, they can handle multiple operations executing in the background. When one of these operations completes, the kernel tells Node.js so that the appropriate callback may be added to the poll queue to eventually be executed.
- Question 28Mid
How would you read files in sequence in Node.js? Provide a code example
- Node.js JavaScript
Reveal answerHide answer
If you want to read the files in sequence, just use a modern for … of loop, in which await will work as expected:
async function printFiles () { const files = await getFilePaths(); for (const file of files) { const contents = await fs.readFile(file, 'utf8'); console.log(contents); } } - Question 29Mid
What is the difference between require(x) and ES6 import x in Node.js?
- Node.js
Reveal answerHide answer
import (ES6) is the future of the Javascript language in both Node.js and the browser and is used in ECMAScript modules (ESM modules) for loading other modules, eitherstatically or dynamically. You can use named imports to selectively load only the pieces you need. That can save memory. Import can be asynchronous (and in current ES6 Module Loader, it in fact is) and can perform a little better. ES6 → import , export default , export// hello.js
function hello() {return 'hello'
} export default hello // app.js import hello from './hello' hello() // returns hello require() is the original way that Node.js loaded modules and is used in CommonJS modules. require() is natively supported in Node.js, but not in browsers (though there are some 3rd party libraries that have require-like module loaders for the browser).You can have dynamic loading where the loaded module name isn't predefined /static, or where you conditionally load a module only if it's "truly required" (depending on certain code flow). Loading is synchronous. That means if you have multiple requires, they are loaded and processed one by one. CommonJS → require , module.exports , exports.foo// hello.js
function hello1() {return 'hello1'
} function hello2() {return 'hello2'
} module.exports = { hello1, hello2 } // app.js const hello = require('./hello') hello.hello1() // returns hello1 hello.hello2() // returns hello2 - Question 30Mid
Provide some of the reasons not to use Node.js
- Node.js
Reveal answerHide answer
It runs Javascript, which has no compile-time type checking. For large, complex safety-critical systems, or projects including collaboration between different organizations, a language which encourages contractual interfaces and provides static type checking may save you some debugging time (and explosions) in the long run. (Although the JVM is stuck with null , so please use Haskell for your nuclear reactors.) Added to that, many of the packages in NPM are a little raw, and still under rapid development. Some libraries for older frameworks have undergone a decade of testing and bugfixing, and are very stable by now. Npmjs.org has no mechanism to rate packages, which has lead to a proliferation of packages doing more or less the same thing, out of which a large percentage are no longer maintained. Nested callback hell. (Of course there are 20 different solutions to this...) The ever-growing pool of packages can make one NodeJS project appear radically different from the next. There is a large diversity in implementations due to the huge number of options available (e.g. Express/Sails.js/Meteor/Derby). This can sometimes make it harder for a new developer to jump in on a Node project. Contrast that with a Rails developer joining an existing project: he should be able to get familiar with the app pretty quickly because all Rails apps are encouraged to use a similar structure. Dealing with files can be a bit of a pain. Things that are trivial in other languages, like reading a line from a text file, are weird enough to do with Node.js that there's a StackOverflow question on that with 80+ upvotes. There's no simple way to read one record at a time from a CSV file. Etc.
- Question 31Mid
What is a Blocking Code in Node.js?
- Node.js
Reveal answerHide answer
A blocking call causes results to be returned synchronously.
Performing a blocking system call causes the process to enter the blocked state. Control is let back to the process only after the I/O event that is being waited upon occurs.
const fs = require("fs"); const contents = fs.readFileSync("file.txt", "utf8"); // this line is not reached until the read results are in console.log(contents); - Question 32Mid
Explain the concept of Domain in Node.js
- Node.js
Reveal answerHide answer
Domains provide a way to handle multiple different IO operations as a single group. If any of the event emitters or callbacks registered to a domain emit an error event, or throw an error, then the domain object will be notified, rather than losing the context of the error in the process.on('uncaughtException') handler, or causing the program to exit immediately with an error code. Domain error handlers are not a substitute for closing down a process when an error occurs. The safest way to respond to a thrown error is to shut down the process. In a normal web server, the better approach is to send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker.
var domain = require('domain'); var d = domain.create(); // Domain emits 'error' when it's given an unhandled error d.on('error', function(err) { console.log(err.stack); // Our handler should deal with the error in an appropriate way });// Enter this domain d.run(function() { // If an un-handled error originates from here, process.domain will handle it console.log(process.domain === d); // true });// domain has now exited. Any errors in code past this point will not be caught. - Question 33Mid
What is the relationship between Node.js and V8?
- Node.js
Reveal answerHide answer
V8 is the Javascript engine inside of node.js that parses and runs your Javascript. The same V8 engine is used inside of Chrome to run javascript in the Chrome browser. Google open-sourced the V8 engine and the builders of node.js used it to run Javascript in node.js.
- Question 34Mid
What is stream and what are types of streams available in Node.js?
- Node.js
Reveal answerHide answer
A stream is an abstract interface for working with streaming data in Node.js. Streams basically provide two major advantages over using other data handling methods: Memory efficiency: you don't need to load large amounts of data in memory before you are able to process it Time efficiency: it takes way less time to start processing data, since you can start processing as soon as you have it, rather than waiting till the whole data payload is available There are 4 types of streams in Node.js:
- Writable: streams to which we can write data. For example, fs.createWriteStream() lets us write data to a file using streams.
- Readable: streams from which data can be read. For example: fs.createReadStream() lets us read the contents of a file.
- Duplex: streams that are both Readable and Writable. For example, net.Socket
- Transform: streams that can modify or transform the data as it is written and read. For example, in the instance of file-compression, you can write compressed data and read decompressed data to and from a file.
- Question 35Mid
What is the preferred method of resolving unhandled exceptions in Node.js?
- Node.js
Reveal answerHide answer
Unhandled exceptions in Node.js can be caught at the Process level by attaching a handler for uncaughtException event.
process.on('uncaughtException', function(err) { console.log('Caught exception: ' + err); });However, uncaughtException is a very crude mechanism for exception handling and may be removed from Node.js in the future. An exception that has bubbled all the way up to the Process level means that your application, and Node.js may be in an undefined state, and the only sensible approach would be to restart everything. The preferred way is to add another layer between your application and the Node.js process which is called the domain. Domains provide a way to handle multiple different I/O operations as a single group. So, by having your application, or part of it, running in a separate domain, you can safely handle exceptions at the domain level, before they reach the Process level.
- Question 36Mid
How does Node.js handle Child Threads?
- Node.js
Reveal answerHide answer
Node.js, in its essence, is a single thread process. It does not expose child threads and thread management methods to the developer. js does spawn child threads for certain tasks such as asynchronous I/O, but these run behind the scenes and do not execute any application JavaScript code, nor block the main event loop. If threading support is desired in a Node.js application, there are tools available to enable it, such as the ChildProcess module.
- Question 37Mid
When should we use Node.js?
- Node.js
Reveal answerHide answer
Node.js is well suited for applications that have a lot of concurrent connections and each request only needs very few CPU cycles and situations in which you'll be reusing a lot of code across the client/server gap (JavaScript all the time, Lingua Franca on the whole stack) because the event loop (with all the other clients) is blocked during the execution of a function. Node.js is best suited for real-time applications: online games, collaboration tools, chat rooms, API's or anything, where what one user does with the application, needs to be seen by other users immediately, without a page refresh. In addition, Node.js is especially suited for applications where you'd like to maintain a persistent connection from the browser back to the server. Using a technique known as "long-polling", you can write an application that sends updates to the user in real time. Doing long polling on many of the web's giants, like Ruby on Rails or Django, would create immense load on the server, because each active client eats up one server process. This situation amounts to a tarpit attack. When you use something like Node.js, the server has no need of maintaining separate threads for each open connection.
- Question 38Mid
What is Event Loop in Node.js?
- Node.js
Reveal answerHide answer
Generally speaking, the event loop is a mechanism that waits for and dispatches events or messages in a program. In Node.js, event loops are the central control flow constructs. For example, every time a request is about to be handled, it’s put on the event loop and processed as soon as it’s ready to be processed. Node, instead of doing it on its own, delegates the responsibility of handling the system. Because of such behaviour, Node is not actively waiting for this task to finish and can handle other requests in the meantime. The event loop makes Node.js faster and more efficient than other technologies
- Question 39Mid
What is N-API in Node.js?
- Node.js
Reveal answerHide answer
N-API (pronounced N as in the letter, followed by API) is an API for building native Addons. It is independent from the underlying JavaScript runtime (ex V8) and is maintained as part of Node.js itself. This API will be Application Binary Interface (ABI) stable across versions of Node.js. It is intended to insulate Addons from changes in the underlying JavaScript engine and allow modules compiled for one version to run on later versions of Node.js without recompilation.
- Question 40Mid
What are express.json() and express.urlencoded() in Express.js?
- Node.js
Reveal answerHide answer
The json and urlencoded middleware are both part of bodyParser .
bodyParser([options]) :Returns middleware that parses both json and urlencoded . The options are passed to both middleware.
bodyParser.json([options]) :Returns middleware that only parses json . The options are: strict - only parse objects and arrays limit <1mb> - maximum request body size reviver - parsed to JSON.parse()
bodyParser.urlencoded([options])Returns middleware that only parses urlencoded with the qs module. The options are: limit <1mb> - maximum request body size
- Question 41Mid
Is there any difference between res.send and return res.send in Express.js?
- Node.js
Reveal answerHide answer
The return keyword returns from your function, thus ending its execution. This means that any lines of code after it will not be executed.
In some circumstances, you may want to use res.send and then do other stuff.
app.get('/', function(req, res) { res.send('I am a beautiful butterfly'); console.log("This gets executed"); }); app.get('/', function(req, res) { return res.send('I am a beautiful butterfly'); console.log("This does not get executed"); }) - Question 42Mid
What is the difference between cluster and worker_threads packages in Node.js?
- Node.js
Reveal answerHide answer
Effectively what you are differing is process based vs thread based. Threads share memory (e.g. SharedArrayBuffer ) whereas processes don't. Cluster One process is launched on each CPU and can communicate via IPC. Each process has its own memory with its own Node (v8) instance. Creating tons of them may create memory issues. Great for spawning many HTTP servers that share the same port b/c the master main process will multiplex the requests to the child processes. Worker threads One process total Creates multiple threads with each thread having one Node instance (one event loop, one JS engine). Most Node API's are available to each thread except a few. So essentially Node is embedding itself and creating a new thread. Shares memory with other threads (e.g. SharedArrayBuffer ) Great for CPU intensive tasks like processing data or accessing the file system. Because NodeJS is single- threaded, synchronous tasks can be made more efficient with workers
- Question 43Mid
When would you use global variables in Node.js? Are they always bad?
- Node.js
Reveal answerHide answer
Global variables can be used in Node when used wisely: Use global variables when they are not about to be changed. In some cases, globals are the unique way to work. I use it commonly to store constant values, like global.MY_CONST = 10 , and use it across my whole project. If tomorrow I want to change it in the whole project, I only need to change it in the app.js (Node example, in this case). Anyways it's more recommended that you will be using the process.env object or config file.
- Question 44Mid
How to use global variable in Node.js?
- Node.js
Reveal answerHide answer
If you do want a global variable you can do:
global.logger = new logger(customConfig); global.myNumber; //Delclaration of the global variable - undefined global.myNumber = 5; //Global variable initialized to value 5. var myNumberSquared = global.myNumber * global.myNumber; //Using the global variable. - Question 45Mid
What is the difference between browser global scope andNode.js global scope?
- Node.js
Reveal answerHide answer
In browser: The global scope is the window object. The top-level scope is the global scope. If you're in the global scope var something will define a global variable. In Node.js: The global scope of a module is the module itself When you define a variable in the global scope of your Node.js module, it will be local to this module The top-level is not the global scope var something inside a Node.js module will be local to that module.
- Question 46Mid
What is export default in JavaScript?
- Node.js JavaScript
Reveal answerHide answer
As the name says, it's used to export functions, objects, classes or expressions from script files or modules Utiliites.js
export function cube(x) { return x * x * x; } export const foo = Math.PI + Math.SQRT2;This can be imported and used as App.js
import { cube, foo } from 'Utilities'; console.log(cube(3)); // 27 console.log(foo); // 4.555806215962888Or
import * as utilities from 'Utilities'; console.log(utilities.cube(3)); // 27 console.log(utilities.foo); // 4.555806215962888When export default is used, this is much simpler. Script files just exports one thing. cube.js
export default function cube(x) { return x * x * x; }; and used as App.js import Cube from 'cube'; console.log(Cube(3)); // 27 - Question 47Mid
What are the use cases for the Node.js vm core module?
- Node.js
Reveal answerHide answer
It can be used to safely execute a piece of code contained in a string or file. The execution is performed in a separate environment that by default has no access to the environment of the program that created it. Moreover, you can specify execution timeout and context-specific error handling.
- Question 48Mid
Are you familiar with differences between Node.js modules and ES6 modules?
- Node.js
Reveal answerHide answer
The modules used in Node.js follow a module specification known as the CommonJS specification. The recent updates to the JavaScript programming language, in the form of ES6, specify changes to the language, adding things like new class syntax and a module system. This module system is different from Node.js modules. To import ES6 module, we'd use the ES6 import functionality. Now ES6 modules are incompatible with Node.js modules. This has to do with the way modules are loaded differently between the two formats. If you use a compiler like Babel, you can mix and match module formats.
- Question 49Mid
What is difference between synchronous and asynchronous method of fs module?
- Node.js
Reveal answerHide answer
Every method in fs module has synchronous as well as asynchronous form. Asynchronous methods takes a last parameter as completion function callback and first parameter of the callback function is error. It is preferred to use asynchronous method instead of Synchronous method as former never blocks the program execution where the latter one does.
- Question 50Mid
How do you debug Node.js applications?
- Node.js
Reveal answerHide answer
Node has its own built in GUI debugger as of version 6.3 (using Chrome's DevTools). node --inspect server.js Some other options for debugging are: Joyent's Guide Debugger Node Inspector Visual Studio Code Cloud9 Brackets
- Question 51Mid
When should I use EventEmitter ?
- Node.js
Reveal answerHide answer
Use it whenever it makes sense for code to subscribe to something rather than get a callback from something. The typical use case would be that there's multiple blocks of code in your application that may need to do something when an event happens. Consider:
// get the reference of EventEmitter class of events module var events = require('events');//create an object of EventEmitter class by using above reference var em = new events.EventEmitter();//Subscribe for FirstEvent em.on('FirstEvent', function (data) { console.log('First subscriber: ' + data); });// Raising FirstEvent em.emit('FirstEvent', 'This is my first Node.js event emitter example.'); - Question 52Mid
What Are Buffer and why to use them in Node.js?
- Node.js
Reveal answerHide answer
Pure JavaScript, while great with unicode-encoded strings, does not handle straight binary data very well. This is fine on the browser, where most data is in the form of strings. However, Node.js servers have to also deal with TCP streams and reading and writing to the filesystem, both of which make it necessary to deal with purely binary streams of data. The Buffer class in Node.js is designed to handle raw binary data. Each buffer corresponds to some raw memory allocated outside V8. Buffers act somewhat like arrays of integers, but aren't resizable and have a whole bunch of methods specifically for binary data.
var buffer = Buffer.alloc(16) buffer.write("Hello", "utf-8") buffer.write(" world!", 5, "utf-8") buffer.toString('utf-8') - Question 53Mid
Could we run an external process with Node.js?
- Node.js
Reveal answerHide answer
Yes. Child process module enables us to access operating system functionaries or other apps. Scalability is baked into Node and child processes are the key factors to scale our application. You can use child process to run system commands, read large files without blocking event loop, decompose the application into various “nodes” (That’s why it’s called Node). The child process module has the following three major ways to create child processes: spawn - child_process.spawn launches a new process with a given command. exec - child_process.exec method runs a command in a shell/console and buffers the output. exec has a memory limitation of the buffer size of 512k. In this case, it is better to use spawn . fork - The child_process.fork method is a special case of the spawn() to create child processes.
- Question 54Mid
How does concurrency work in Node.js?
- Node.js
Reveal answerHide answer
The thing with node.js is that everything runs concurrently, except for your code. So, what that means is that there are actually lots of threads running inside Node.js virtual machine (or a thread pool if you wish), and those threads are utilized whenever you call an async function like performing i/o operations on files, accessing databases, requesting urls, etc. However, for your code, there is only a single thread, and it processes events from an event queue. So, when you register a callback its reference is actually passed to the background worker thread, and once the async operation is done, new event is added to the event-queue with that callback
When Node gets I/O request it creates or uses a thread to perform that I/O operation and once the operation is done, it pushes the result to the event queue. On each such event, event loop runs and checks the queue and if the execution stack of Node is empty then it adds the queue result to execution stack. This is how Node manages concurrency.
- Question 55Mid
What are Event Emitters?
- Node.js
Reveal answerHide answer
EventEmitter is a class that helps us create a publisher-subscriber pattern in NodeJS. With an event emitter, we can simply raise a new event from a different part of an application, and a listener will listen to the raised event and have some action performed for the event.
import { EventEmitter } from 'events'; const eventEmitter = new EventEmitter();// listen to the event eventEmitter.on('myEvent', () => { console.log('Data Received'); // this function is the event listener });// publish an event eventEmitter.emit('myEvent'); - Question 56Mid
How to avoid Callback Hell in Node.js?
- Node.js
Reveal answerHide answer
Node.js internally uses a single-threaded event loop to process queued events. But this approach may lead to blocking the entire process if there is a task running longer than expected. Node.js addresses this problem by incorporating callbacks also known as higher-order functions. So whenever a long-running process finishes its execution, it triggers the callback associated. Sometimes, it could lead to complex and unreadable code. More the no. of callbacks, longer the chain of returning callbacks would be. There are four solutions which can address the callback hell problem: Make your program modular - It proposes to split the logic into smaller modules. And then join them together from the main module to achieve the desired result. Use async/await mechanism - Async /await is another alternative for consuming promises, and it was implemented in ES8, or ES2017. Async/await is a new way of writing promises that are based on asynchronous code but make asynchronous code look and behave more like synchronous code. Use promises mechanism - Promises give an alternate way to write async code. They either return the result of execution or the error/exception. Implementing promises requires the use of .then() function which waits for the promise object to return. It takes two optional arguments, both functions. Depending on the state of the promise only one of them will get called. The first function call proceeds if the promise gets fulfilled. However, if the promise gets rejected, then the second function will get called. Use generators - Generators are lightweight routines, they make a function wait and resume via the yield keyword. Generator functions uses a special syntax function* () . They can also suspend and resume
asynchronous operations using constructs such as promises or thunks and turn a synchronous code into asynchronous.
function* HelloGen() { yield 100; yield 400; } var gen = HelloGen(); console.log(gen.next()); // {value: 100, done: false} console.log(gen.next()); // {value: 400, done: false} console.log(gen.next()); // {value: undefined, done: true} - Question 57Mid
What is the difference between setTimeout(fn,0) vs setImmediate(fn) ?
- Node.js
Reveal answerHide answer
setTimeout is simply like calling the function after the delay has finished. Whenever a function is called it is not executed immediately, but queued so that it is executed after all the executing and currently queued event handlers finish first. setTimeout(,0) essentially means executing after all current functions in the present queue get executed. No guarantees can be made about how long it could take. setImmediate is similar in this regard except that it doesn't use a queue of functions. It checks the queue of I/O event handlers. If all I/O events in the current snapshot are processed, it executes the callback. It queues them immediately after the last I/O handler somewhat like process.nextTick . So it is faster.
- Question 58Mid
What is Stream Chaining in Node.js?
- Node.js
Reveal answerHide answer
Chanining is a mechanism to connect output of one stream to another stream and create a chain of multiple stream operations. It is normally used with piping operations. if we’re piping into a duplex stream, we can chain pipe calls just like we do in Linux: readableSrc
.pipe(transformStream1) .pipe(transformStream2) .pipe(finalWrtitableDest)The pipe method returns the destination stream, which enabled us to do the chaining above. For streams a (readable), b and c (duplex), and d (writable), we can:
a.pipe(b).pipe(c).pipe(d) # Which is equivalent to: a.pipe(b) b.pipe(c) c.pipe(d) # Which, in Linux, is equivalent to: $ a | b | c | d - Question 59Mid
What is the purpose of using assert module in Node.js
- Node.js
Reveal answerHide answer
Assert module in node.js is an inbuilt module which can be used to write tests. It provides a way to perform unit tests on node.js expressions. If the test case is failed or 0 or false then, an error is raised. If the test case is passed or 1 or true then it provides no feedback. For example:
var assert = require('assert'); function demo(x,y,z) { var value = x + y + z; return value; } var output = demo(4,1,10); console.log("Output : " + output); var expected_output = 15; console.log("Expected Output : " + expected_output); assert( output === expected_output , 'Test case is true so this will not be printed');// Output : 15 // Expected Output : 15 - Question 60Mid
What is chai and chai-http in Node.js userland?
- Node.js
Reveal answerHide answer
Chai offers an assertion library for Node.js. Chai includes basic assertions that you can use to verify behavior. Some of the more popular ones include: should
expect assert These can be used in your tests to evaluate conditions of code you’re testing, such as the following borrowed from chai’s homepage:
chai.should(); foo.should.be.a('string'); foo.should.equal('bar'); foo.should.have.lengthOf(3); tea.should.have.property('flavors') .with.lengthOf(3);Chai-http is a plugin that offers a full-fledged test runner that will actually run your application and test its endpoints directly:
describe('GET /films-list', () => { it('should return a list of films when called', done => { chai .request(app) .get('/films-list') .end((err, res) => { res.should.have.status(200); expect(res.body).to.deep.equal(starwarsFilmListMock); done(); }); }); });With chai-http, the test runner starts your application, calls the requested endpoint, and then brings it down all in one command. This is really powerful and helps with integration testing of your application.
- Question 61Mid
Would you use Node.js assert library vs. other assert libraries like chai ? Why?
- Node.js
Reveal answerHide answer
Basically, you can achieve all the things with Node's very own assert module that you can do with all the other modules out there. Sticking to node.js assert limits your dependency list. There is no technical reason why to prefer one over the other, but readability and null compatibility may be reasons. The only reason why chai 's assert exist is so if you read the code you can get a better understanding of the tests, but that's about it. Compare: For example, testing for a null value with Node.js:
assert(foo === null);And using chai:
assert.isNull(foo); - Question 62Mid
What is Mocha in Node.js userland?
- Node.js
Reveal answerHide answer
Mocha is a test runner that enables you to exercise your Node.js code. It works well with any Node.js project, and follows the basic Jasmine syntax similar to the following:
describe('Array', function() { describe('#indexOf()', function() { it('should return -1 when the value is not present', function() { assert.equal([1, 2, 3].indexOf(4), -1); }); }); });With mocha, you can also include the use of assertion libraries like assert, expect, and others.
- Question 117Mid
What is the built-in node:test module?
- Node.js
- testing
- node:test
Reveal answerHide answer
node:test is Node.js's built-in test runner. It provides test and suite APIs, hooks, mocking utilities, filtering, watch-mode support, and reporting without requiring a third-party test framework. It is a strong default for libraries and services that do not need framework-specific integrations.
Reviewed sources
- Question 118Mid
How does native fetch() work in modern Node.js?
- Node.js
- fetch
- Undici
- HTTP
Reveal answerHide answer
Modern Node.js exposes a browser-compatible global fetch() implementation powered by Undici. It returns a Promise and works with web-standard types such as Request, Response, Headers, FormData, and AbortController. Production code should still define cancellation or timeout policies, handle non-2xx responses explicitly, and understand streaming and connection reuse.
Senior questions
37 questions- Question 63Senior
Do I need Dependency Injection in Node.js and how to deal with it?
- Node.js Dependency Injection
Reveal answerHide answer
Due to the untyped, dynamic nature of JavaScript, you can actually do quite a lot without resorting to the dependency injection (DI) pattern or using a DI framework. The great thing about JS is that you can modify just about anything to achieve what you want. However, as an application grows larger and more complex, DI can definitely help the maintainability of your code. Now the real question is, what can you achieve with a Node.js DI container, compared to a simple require() or import ? Pros: better testability: modules accepts their dependencies as input Inversion of Control: decide how to wire your modules without touching the main code of your application. a customizable algorithm for resolving modules: dependencies have "virtual" identifiers, usually they are not bound to a path on the filesystem. Better extensibility: enabled by IoC and "virtual" identifiers. Other fancy stuff possible: Async initialization Module lifecycle management Extensibility of the DI container itself Can easily implement higher level abstractions (e.g. AOP) Cons: Different from the Node.js "experience": using DI definitely feels like you are deviating from the Node way of thinking. The relationship between a dependency and its implementation is not always explicit. A dependency may be resolved at runtime and influenced by various parameters. The code becomes more difficult to understand and debug Slower startup time
Most DI containers will not play well with module bundlers like Browserify and Webpack. As with anything related to software development, choosing between DI or require() / import depends on your requirements, your system complexity, and your programming style.
- Question 64Senior
How can you have one global variable between all clustered workers in Node.js?
- Node.js
Reveal answerHide answer
To accomplish this, you will want to use the cluster module available in Node.js to message between the workers and the master. The counter variable is stored in the master process in this example and notifies each worker when the counter is updated. If one worker sends a message to update the counter, the master updates it and then notified each worker. If you are looking for the exact memory location to be shared between different processes, this is not possible since Node.js is single-threaded.
const cluster = require('cluster'); const INCREMENT = 'INCREMENT'; const COUNTER = 'COUNTER'; if (cluster.isMaster) { cluster.fork(); cluster.fork(); let counter = 0; cluster.on('message', (worker, msg, handle) => { if (msg.topic && msg.topic === INCREMENT) { // here we increment the counter counter++; for (const id in cluster.workers) { // Here we notify each worker of the updated value cluster.workers[id].send({ topic: COUNTER, value: counter }); } } }); } else if (cluster.isWorker) { console.log(`Worker id: ${cluster.worker.id}`); // Here is a function that requests the counter be updated in the master from a worker. function incrementCounter() { process.send({ topic: INCREMENT }); }// A dummy timeout to call the incrementCounter function setTimeout(incrementCounter, 1000 * cluster.worker.id);// Handle the counter update process.on('message', (msg) => { if (msg.topic && msg.topic === COUNTER) { console.log(`${cluster.worker.id}/${process.pid}: ${msg.topic} ${msg.value}`); } }); } - Question 65Senior
List some differences between CommonJS module loader andECMAScript module loader
- Node.js
Reveal answerHide answer
CommonJS module loader: It is fully synchronous. It is responsible for handling require() calls. It is monkey patchable. It supports folders as modules. It treats .json as JSON text files. ECMAScript module loader: It is asynchronous. It is responsible for handling import statements and import() expressions. It is not monkey patchable, and can be customized using loader hooks. It does not support folders as modules, directory indexes(e.g. './startup/index.js' ) must be fully specified. It can load JSON modules, but an import assertion is required.
- Question 66Senior
Compare strict vs legacy mode for Assert module in Node.js
- Node.js
Reveal answerHide answer
The assert module provides a simple set of assertion tests that can be used to test invariants. A strict and a legacy mode exist, while it is recommended to only use strict mode . When using the strict mode , any assert function will use the equality used in the strict function mode. So assert.deepEqual() will, for example, work the same as assert.deepStrictEqual() . On top of that, error messages which involve objects produce an error diff instead of displaying both objects. That is not the case for the legacy mode.
- Question 67Senior
Explain what is Arrange-Act-Assert pattern?
- Node.js Unit Testing
Reveal answerHide answer
Arrange-Act-Assert is a great way to structure test cases. It prescribes an order of operations: 1. Arrange inputs and targets. Arrange steps should set up the test case. Does the test require any objects or special settings? Does it need to prep a database? Does it need to log into a web app? Handle all of these operations at the start of the test. 2. Act on the target behaviour. Act steps should cover the main thing to be tested. This could be calling a function or method, calling a REST API, or interacting with a web page. Keep actions focused on the target behaviour.
Assert expected outcomes. Act steps should elicit some sort of response. Assert steps verify the goodness or badness of that response. Sometimes, assertions are as simple as checking numeric or string values. Other times, they may require checking multiple facets of a system. Assertions will ultimately determine if the test passes or fails.
- Question 68Senior
What is the difference between fork() & spawn() in Node.js?
- Node.js
Reveal answerHide answer
The spawn method spawns an external application in a new process and returns a streaming interface for I/O. As spawn returns a stream based object, it’s great for handling applications that produce large amounts of data or for working with data as it reads in. fork is a special instance of spawn , that runs a fresh instance of the V8 engine. This means you can essentially create multiple workers, running on the exact same Node code base, or perhaps a different module for a specific task. This is most useful for creating a worker pool. While node's async event model allows a single core of a machine to be used fairly efficiently, it doesn't allow a node process to make use of multi-core machines. The easiest way to accomplish this is to run multiple copies of the same program, on a single processor.
- Question 69Senior
What is the difference between the child_process spawn and execute functions in Node.js? When to use each one?
- Node.js
Reveal answerHide answer
child process created by spawn() does not spawn a shell streams the data returned by the child process (data flow is constant)has no data transfer size limit
child process created by exec()does spawn a shell in which the passed command is executed buffers the data (waits till the process closes and transfers the data in on chunk) maximum data transfer up to Node.js v.12.x was 200kb (by default), but since Node.js v.12x was
increased to 1MB (by default)Spawn is a command designed to run system commands. spawn is more suitable for long-running processes with huge output. spawn streams input/output with the child process. spawn opens streams for stdout and stderr with ondata events. Use exec if you need such features as shell pipes, redirects or even if you need exec for more than one program at one time. exec just returns a buffer with stdout and stderr as strings.
- Question 70Senior
Compare PM2 Cluster Mode vs. Node.js Cluster module usage
- Node.js
Reveal answerHide answer
They basically do the same. PM2 is a Production Process Manager for Node.js applications with a built-in Load Balancer. When properly configured, PM2 will automatically run your app in cluster mode, spawn workers for you, and take care of spawning new workers when a worker dies. PM2 will use Node Cluster under the hood, it will make things easier since you don't have to programmatically handle forking in your code, just run it as is. Note that Cluster Mode will not support session stickiness so make sure your app is stateless.
- Question 71Senior
What is the difference between Cluster and Fork mode in PM2?
- Node.js
Reveal answerHide answer
The main difference between fork_mode and cluster_mode is that it orders pm2 to use either the child_process.fork api or the cluster API. The fork mode as a basic process spawning. This allows to change the exec_interpreter , so that you can run a php or a python server with pm2. This mode is very useful because it enables a lot of possibilities. For example, you could launch multiple servers on pre-established ports which will then be load-balanced by HAProxy or Nginx. The cluster will only work with node as it's exec_interpreter because it will access to the nodejs cluster
module (eg: isMaster , fork methods etc.). This is great for zero-configuration process managementbecause the process will automatically be forked in multiple instances. For example pm2 start -i 4 server.js will launch 4 instances of server.js and let the cluster module handle load balancing.
- Question 72Senior
What is the difference between pm2 restart and pm2 reload ?
- Node.js
Reveal answerHide answer
The difference is documented here: As opposed to restart , which kills and restarts the process, reload achieves a 0-second-downtime reload. The latter means (found here): With reload, pm2 restarts all processes one by one, always keeping at least one process running. It also states that: If the reload system hasn’t managed to reload your application, a timeout will fallback to a classic restart.
- Question 73Senior
When would you use import * as X from 'X' ?
- Node.js JavaScript
Reveal answerHide answer
Modules with multiple (and even single) exports which do not define a default export will need to have all exports assigned to a named variable, like:
import * as whatever from 'package'; - Question 74Senior
How do you convert an existing callback API to promises?
- Node.js
Reveal answerHide answer
Problem
How to convert this callback code to Promise API? Provide some examples.
var request = require('request'); //http wrapped module function requestWrapper(url, callback) { request.get(url, function (err, response) { if (err) { callback(err); } else{ callback(null, response); } }) } requestWrapper(url, function (err, response) { console.log(err, response) }) ### SolutionConsider:
var request = require('request'); function requestWrapper(url) { return new Promise(function (resolve, reject) { //returning promise request.get(url, function (err, response) { if (err) { reject(err); //promise reject } else{ resolve(response); //promise resolve } }) }) }// usage requestWrapper('http://localhost:8080/promise_request/1'). then(function(response){ console.log(response) //resolve callback(success) }). catch(function(error){ console.log(error) //reject callback(failure) }) - Question 75Senior
How to gracefully shutdown Node.js server?
- Node.js
Reveal answerHide answer
We can gracefully shutdown Node.js server by using the generic signal called SIGTERM or SIGINT which is used for program termination. We need to call SIGTERM or SIGINT which will terminate the program and clean up the resources utilized by the program.
- Question 76Senior
How would you handle errors for async code in Node.js?
- Node.js
Reveal answerHide answer
Handling async errors in callback style (error-first approach) is probably the fastest way to hell (a.k.a the pyramid of doom). It's better to use a reputable promise library or async-await instead which enables a much more compact and familiar code syntax like try-catch. Consider promises to catch errors:
doWork() .then(doWork) .then(doOtherWork) .then((result) => doWork) .catch((error) => {throw error;}) .then(verify);or using async/await:
async function check(req, res) { try { const a = await someOtherFunction(); const b = await somethingElseFunction(); res.send("result") } catch (error) { res.send(error.stack); } } - Question 77Senior
How would you prevent Callback Hell without using promises, async or generators?
- Node.js JavaScript
Reveal answerHide answer
- Don't nest functions. Give them names and place them at the top level of your program. Keep your code shallow.
- Use function hoisting to your advantage to move functions 'below the fold'
- Handle every single error in every one of your callbacks. Use a linter like standard to help you with this.
- Modularize. Create reusable functions and place them in a module to reduce the cognitive load required to understand your code. Splitting your code into small pieces like this also helps you handle errors, write tests, forces you to create a stable and documented public API for your code, and helps with refactoring. The most important aspect of avoiding callback hell is moving functions out of the way so that the flow of the program can be more easily understood without newcomers having to wade through all the detail of the functions to get to the meat of what the program is trying to do.
- Question 78Senior
Does JavaScript have a map function to iterate over an object properties?
- Node.js JavaScript
Reveal answerHide answer
Consider solution that returns a new object and leaves the original object as it is
var myObject = { 'a': 1, 'b': 2, 'c': 3 };// returns a new object with the values at each key mapped using mapFn(value) function objectMap(object, mapFn) { return Object.keys(object).reduce(function(result, key) { result[key] = mapFn(object[key])return result
}, {}) } var newObject = objectMap(myObject, function(value) {return value * 2
}) console.log(newObject); // => { 'a': 2, 'b': 4, 'c': 6 } console.log(myObject); // => { 'a': 1, 'b': 2, 'c': 3 }Or with ES6 fromEntries , entries features:
const objectMap = (obj, fn) => Object.fromEntries( Object.entries(obj).map( ([k, v], i) => [k, fn(v, k, i)] ) ) const myObject = { a: 1, b: 2, c: 3 } console.log(objectMap(myObject, v => 2 * v)) - Question 79Senior
When to use Synchronous vs Asynchronous code in Node.js?
- Node.js
Reveal answerHide answer
Use sync for in-memory operations — async is a complete waste when you aren’t making blocking calls. Use async when designing a library that makes blocking calls — unless you know all users want to use your library synchronously. You can add synchronous code as a feature once you’ve finished the async version. Use async when a library you depend on forces async — because you have no choice. But consider contributing a synchronous version of the library. Use sync for non-parallel tasks — such as computations or system-administration scripts. In sum: async is often a mistake. Code appropriately.
- Question 80Senior
Is it possible to use Class in Node.js?
- Node.js
Reveal answerHide answer
With ES6, you are able to make "actual" classes just like this:
class Animal { constructor(name) { this.name = name; } print() { console.log('Name is :' + this.name); } }You can export a class just like anything else:
module.exports = class Animal { };Once imported into another module, then you can treat it as if it were defined in that file:
var Animal = require('./Animal'); class Cat extends Animal { ... } - Question 81Senior
How the V8 engine works?
- Node.js
Reveal answerHide answer
V8 is a JavaScript engine built at the google development center, in Germany. It is open source and written in C++. It is used for both client side (Google Chrome) and server side (node.js) JavaScript applications. V8 was first designed to increase the performance of the JavaScript execution inside web browsers. In order to obtain speed, V8 translates JavaScript code into more efficient machine code instead of using an interpreter. It compiles JavaScript code into machine code at execution by implementing a JIT (Just-In-Time) compiler like a lot of modern JavaScript engines such as SpiderMonkey or Rhino (Mozilla) are doing. The main difference with V8 is that it doesn’t produce bytecode or any intermediate code.
- Question 82Senior
Can Node.js work without V8?
- Node.js
Reveal answerHide answer
No. The current node.js binary cannot work without V8. It would have no Javascript engine and thus no ability to run code which would obviously render it non-functional. Node.js was not designed to run with any other Javascript engine and, in fact, all the native code bindings that come with node.js (such as the fs module or the net module) all rely on the specific V8 interface between C++ and Javascript. There is an effort by Microsoft to allow the Chakra Javascript engine (that's the engine in Edge) to be used with node.js. Node.js can actually function to some extent without V8, through use of the node-chakracore project. There is ongoing work to reduce the tight coupling between V8 and Node, so that different JavaScript engines can be used in-place.
- Question 83Senior
What are async functions in Node? Provide some examples.
- Node.js
Reveal answerHide answer
With the release of Node.js 8, the long awaited async functions have landed in Node.js as well. ES 2017 introduced Asynchronous functions. Async functions are essentially a cleaner way to work with asynchronous code in JavaScript. Async/Await is: The newest way to write asynchronous code in JavaScript. It is non blocking (just like promises and callbacks). Async/Await was created to simplify the process of working with and writing chained promises.
Async functions return a Promise. If the function throws an error, the Promise will be rejected. If the function returns a value, the Promise will be resolved. Async functions can make use of the await expression. This will pause the async function and wait for thePromise to resolve prior to moving on. Consider the code:
function doubleAfter2Seconds(x) { return new Promise(resolve => { setTimeout(() => { resolve(x * 2); }, 2000); }); }What if we want to run a few different values through our function and add the result? Promise-based solution will be:
function addPromise(x) { return new Promise(resolve => { doubleAfter2Seconds(10).then((a) => { doubleAfter2Seconds(20).then((b) => { doubleAfter2Seconds(30).then((c) => { resolve(x + a + b + c); }) }) }) }); } addPromise(10).then((sum) => { console.log(sum); });Async/Await solution will look like:
async function addAsync(x) { const a = await doubleAfter2Seconds(10); const b = await doubleAfter2Seconds(20); const c = await doubleAfter2Seconds(30); return x + a + b + c; } addAsync(10).then((sum) => { console.log(sum); }); - Question 84Senior
What's the difference between dependencies,devDependencies and peerDependencies in package.json file?
- Node.js
Reveal answerHide answer
dependencies - Dependencies that your project needs to run, like a library that provides functions that you call from your code. They are installed transitively (if A depends on B depends on C, npm install on A will install B and C). devDependencies - Dependencies you only need during development or releasing, like compilers that take your code and compile it into javascript, test frameworks or documentation generators. They are not installed transitively (if A depends on B dev-depends on C, npm install on A will install B only). peerDependencies - Dependencies that your project hooks into, or modifies, in the parent project, usually a plugin for some other library or tool. It is just intended to be a check, making sure that the parent project (project that will depend on your project) has a dependency on the project you hook into. So if you make a plugin C that adds functionality to library B, then someone making a project A will need to have a dependency on B if they have a dependency on C. They are not installed (unless npm < 3), they are only checked for.
- Question 85Senior
What is Piping in Node?
- Node.js
Reveal answerHide answer
Piping is a mechanism to connect output of one stream to another stream. It is normally used to get data from one stream and to pass output of that stream to another stream. There is no limit on piping operations.
var fs = require('fs') var readable = fs.createReadStream('file1.txt') var writable = fs.createWriteStream('file2.txt') readable.pipe(writable) // returns writableWhen writable streams are also readable streams, i.e. when they're duplex streams, you can continue piping it to other writable streams.
var zlib = require('zlib') fs.createReadStream('style.css') .pipe(zlib.createGzip()) // The returned object, zlib.Gzip, is a duplex stream. .pipe(fs.createWriteStream('style.css.gz')Readable streams can also be piped into multiple streams.
var readable = fs.createReadStream('source.css') readable.pipe(zlib.createGzip()).pipe(fs.createWriteStream('output.css.gz')) readable.pipe(fs.createWriteStream('output.css') - Question 86Senior
Provide some example of config file separation for dev and prod environments
- Node.js
Reveal answerHide answer
A perfect and flawless configuration setup should ensure: keys can be read from file AND from environment variable secrets are kept outside committed code config is hierarchical for easier findability Consider the following config file:
var config = { production: { mongo : { billing: '****' } }, default: { mongo : { billing: '****' } } } exports.get = function get(env) { return config[env] || config.default; } And it's usage: const config = require('./config/config.js').get(process.env.NODE_ENV); const dbconn = mongoose.createConnection(config.mongo.billing); - Question 87Senior
What is LTS releases of Node.js why should you care?
- Node.js
Reveal answerHide answer
An LTS(Long Term Support) version of Node.js receives all the critical bug fixes, security updates and performance improvements. LTS versions of Node.js are supported for at least 18 months and are indicated by even version numbers (e.g. 4, 6, 8). They're best for production since the LTS release line is focussed on stability and security, whereas theCurrent release line has a shorter lifespan and more frequent updates to the code. Changes to LTS versions are limited to bug fixes for stability, security updates, possible npm updates, documentation updates and certain performance improvements that can be demonstrated to not break existing applications.
- Question 88Senior
Explain usage of NODE_ENV
- Node.js
Reveal answerHide answer
Node encourages the convention of using a variable called NODE_ENV to flag whether we’re in production right now. This determination allows components to provide better diagnostics during development, for example by disabling caching or emitting verbose log statements. Setting NODE_ENV to production makes your application roughly 3 times faster.
// Setting environment variables in bash before starting the node process $ NODE_ENV=development $ nodeAnd reading variable:
if (process.env.NODE_ENV === “production”) useCaching = true; - Question 89Senior
What are the Timing features of Node.js?
- Node.js
Reveal answerHide answer
The Timers module in Node.js contains functions that execute code after a set period of time. setTimeout/clearTimeout - can be used to schedule code execution after a designated amount of milliseconds setInterval/clearInterval - can be used to execute a block of code multiple times setImmediate/clearImmediate - will execute code at the end of the current event loop cycle process.nextTick - used to schedule a callback function to be invoked in the next iteration of the Event Loop
function cb(){ console.log('Processed in next iteration'); } process.nextTick(cb); console.log('Processed in the first iteration');Output:
Processed in the first iteration Processed in next iteration - Question 90Senior
Why to use Buffer instead of binary string to handle binary data ?
- Node.js
Reveal answerHide answer
Pure JavaScript does not able to handle straight binary data very well. Since Node.js servers have to deal with TCP streams for reading and writing of data, binary strings will become problematic to work with as it is very slow and has a tendency to break. That's why it is always advisable to use Buffers instead of binary strings to handle binary data.
- Question 91Senior
When not to use Node.js?
- Node.js
Reveal answerHide answer
We can use Node.js for a variety of applications. But it is a single threaded framework, so we should not use it for cases
**where the application requires long processing time (If the server is doing some calculation) **,it won’t be able to process any other requests. Hence, Node.js is best when processing needs less dedicated CPU time.
- Question 92Senior
Is Node.js entirely based on a single-thread?
- Node.js
Reveal answerHide answer
Yes, it’s true that Node.js processes all requests on a single thread. But it’s just a part of the theory behind Node.js design. In fact, more than the single thread mechanism, it makes use of events and callbacks to handle a large no. of requests asynchronously. Moreover, Node.js has an optimized design which utilizes both JavaScript and C++ to guarantee maximum performance. JavaScript executes at the server-side by Google Chrome v8 engine. And the C++ lib UV library takes care of the non-sequential I/O via background workers. To explain it practically, let’s assume there are 100s of requests lined up in Node.js queue. As per design, the main thread of Node.js event loop will receive all of them and forwards to background workers for execution. Once the workers finish processing requests, the registered callbacks get notified on event loop thread to pass the result back to the user.
- Question 93Senior
Does Node.js support multi-core platforms? And is it capable of utilizing all the cores?
- Node.js
Reveal answerHide answer
Yes, Node.js would run on a multi-core system without any issue. But it is by default a single-threaded application, so it can’t completely utilize the multi-core system. However, Node.js can facilitate deployment on multi-core systems where it does use the additional hardware. It packages with a Cluster module which is capable of starting multiple Node.js worker processes that will share the same port.
- Question 94Senior
What is the purpose of __filename variable in Node.js?
- Node.js
Reveal answerHide answer
The __filename represents the filename of the code being executed. This is the resolved absolute path of this code file. For a main program this is not necessarily the same filename used in the command line. The value inside a module is the path to that module file.
- Question 95Senior
How does the Cluster module work? What’s the difference between it and a load balancer?
- Node.js
Reveal answerHide answer
The Cluster module performs fork from your server (at that moment it is already an OS process), thus creating several slave processes. The cluster module supports two methods of distributing incoming connections. The first one (and the default one on all platforms except Windows), is the round-robin approach, where the master process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process. The second approach is where the master process creates the listen socket and sends it to interested workers. The workers then accept incoming connections directly. The difference between a cluster module and a load balancer is that instead of distributing load between processes, the balancer distributes requests.
- Question 115Senior
When should you use worker_threads in Node.js?
- Node.js
- worker_threads
- performance
Reveal answerHide answer
Use worker_threads for CPU-intensive JavaScript that would otherwise block the event loop, such as parsing, compression, image processing, or computation. Workers run JavaScript in separate threads and can communicate with messages or shared memory. They usually do not improve ordinary I/O-heavy work because Node's asynchronous I/O already avoids blocking the JavaScript thread.
Reviewed sources
- Question 116Senior
What is AsyncLocalStorage and when is it useful?
- Node.js
- AsyncLocalStorage
- observability
Reveal answerHide answer
AsyncLocalStorage from node:async_hooks stores request-scoped context across asynchronous operations. It is commonly used for correlation IDs, tracing context, tenant information, and structured logging without manually passing context through every function. Treat the stored data as request context rather than general global state, and disable stores when their lifetime ends if necessary.
Reviewed sources
- Question 119Senior
What is stream backpressure in Node.js?
- Node.js
- streams
- backpressure
Reveal answerHide answer
Backpressure prevents a fast producer from overwhelming a slower consumer. Writable streams signal pressure when write() returns false; producers should wait for the drain event before continuing. pipe() and pipeline() coordinate this automatically in common cases. Respecting backpressure keeps memory usage bounded and improves stability when processing large or continuous data.
- Question 120Senior
How should a Node.js service perform graceful shutdown?
- Node.js
- production
- graceful shutdown
Reveal answerHide answer
On termination signals such as SIGTERM, stop accepting new work, mark the instance unready, finish or bound in-flight requests, close database and message-broker connections, flush essential telemetry, and exit before the platform's shutdown deadline. Use an overall timeout so shutdown cannot hang forever. In containers and orchestrators, coordinate this with readiness checks and the platform's termination grace period.
Reviewed sources
Expert questions
19 questions- Question 96Expert
How many threads does Node actually create?
- Node.js
Reveal answerHide answer
4 extra threads are for use by V8. V8 uses these threads to perform various tasks, such as GC-related background tasks and optimizing compiler tasks.
- Question 97Expert
Does the cluster in Node.js utilizes same event loop?
- Node.js
Reveal answerHide answer
Yes, it uses the same event loop. Incoming requests arrive as incoming TCP requests using the normal TCP events and event loop. They are then load balanced to the clusters using interprocess communication to the clustered processes which also run via the event loop. All processes are normal Node.js apps that are using the regular event loop.
- Question 98Expert
Can Node.js use other engines than V8?
- Node.js
Reveal answerHide answer
Yes. Microsoft Chakra is another JavaScript engine which can be used with Node.js. It’s not officially declared yet.
- Question 99Expert
How would you scale Node application?
- Node.js
Reveal answerHide answer
We can scale Node application in following ways: cloning using Cluster module. decomposing the application into smaller services – i.e micro services.
- Question 100Expert
Why Node.js devs tend to lean towards the Module Requiring vs Dependency Injection?
- Node.js
Reveal answerHide answer
Dependency injection is somewhat the opposite of normal module design. In normal module design, a module uses require() to load in all the other modules that it needs with the goal of making it simple for the caller to use your module. The caller can just require() in your module and your module will load all the other things it needs. With dependency injection, rather than the module loading the things it needs, the caller is required to pass in things (usually objects) that the module needs. This can make certain types of testing easier and it can make mocking certain things for testing purposes easier. Modules and dependency injection are orthogonal: if you need dependency injection for testability or extensibility then use it. If not, importing modules is fine. The great thing about JS is that you can modify just about anything to achieve what you want. This comes in handy when it comes to testing.
- Question 101Expert
What is V8 Templates?
- Node.js
Reveal answerHide answer
A template is a blueprint for JavaScript functions and objects. You can use a template to wrap C++ functions and data structures within JavaScript objects. V8 has two types of templates: Function Templates and Object Templates. Function Template is the blueprint for a single function. You create a JavaScript instance of template by calling the template’s GetFunction method from within the context in which you wish to instantiate the JavaScript function. You can also associate a C++ callback with a function template which is called when the JavaScript function instance is invoked.
Object Template is used to configure objects created with function template as their constructor. You can associate two types of C++ callbacks with object templates: accessor callback and interceptor callback. Accessor callback is invoked when a specific object property is accessed by a script. Interceptor callback is invoked when any object property is accessed by a script. In a nutshell, you can wrap C++ objects\structures within JavaScript objects.
- Question 102Expert
How does libuv work under the hood?
- Node.js
Reveal answerHide answer
There is only one thread that executes JavaScript code and this is the thread where the event loop is running provided by libuv. The execution of callbacks (know that every userland code in a running Node.js application is a callback) is done by the event loop. Libuv by default creates a thread pool with four threads to offload asynchronous work to. Today’s operating systems already provide asynchronous interfaces for many I/O tasks (e.g. AIO on Linux). Whenever possible, libuv will use those asynchronous interfaces, avoiding usage of the thread pool. The event loop as a process is a set of phases with specific tasks that are processed in a round-robin manner. Each phase has a FIFO queue of callbacks to execute. While each phase is special in its own way, 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. timers: this phase executes callbacks scheduled by setTimeout() and setInterval() . pending callbacks: executes I/O callbacks deferred to the next loop iteration. idle, prepare: only used internally. poll: retrieve new I/O events; execute I/O related callbacks (almost all with the exception of close callbacks, the ones scheduled by timers, and setImmediate() ); node will block here when appropriate. check: setImmediate() callbacks are invoked here. close callbacks: some close callbacks, e.g. socket.on('close', ...) .
- Question 103Expert
How V8 compiles JavaScript code?
- Node.js
Reveal answerHide answer
V8 has two compilers: A “Full” Compiler that can generate good code for any JavaScript: good but not great JIT code. The goal of this compiler is to generate code quickly. To achieve its goal, it doesn’t do any type analysis and doesn’t know anything about types. Instead, it uses an Inline Caches or “IC” strategy to refine knowledge about types while the program runs. IC is very efficient and brings about 20 times speed improvment. An Optimizing Compiler that produces great code for most of the JavaScript language. It comes later and re-compiles hot functions. The optimizing compiler takes types from the Inline Cache and make decisions about how to optimize the code better. However, some language features are not supported yet like try/catch blocks for instance. (The workaround for try/catch blocks is to write the “non stable” code in a function and call the function in the try block) V8 also supports de-optimization: the optimizing compiler makes optimistic assumptions from the Inline Cache about the different types, de-optimization comes if these assumptions are invalid. For example, if a hidden class generated was not the one expected, V8 throws away the optimized code and comes back to the Full Compiler to get types again from the Inline Cache. This process is slow and should be avoided by trying to not change functions after they are optimized.
- Question 104Expert
What is the purpose of using hidden classes in V8?
- Node.js
Reveal answerHide answer
JavaScript is a prototype-based language: there are no classes and objects are created by using a cloning process. JavaScript is also dynamically typed: types and type informations are not explicit and properties can be added to and deleted from objects on the fly. Accessing types and properties effectively makes a first big challenge for V8. Instead of using a dictionary-like data structure for storing object properties and doing a dynamic lookup to resolve the property location (like most JavaScript engines do), V8 creates** hidden classes**, at runtime, in order to have an internal representation of the type system and to improve the property access time.
- Question 105Expert
How to solve Process out of Memory Exception in Node.js ?
- Node.js
Reveal answerHide answer
To solve the process out of memory exception in Node.js we need to increase the max-old-space-size . By default the max size of max-old-space-size is 512 mb which you can increase by the command: node --max-old-space-size=1024 file.js
- Question 106Expert
Explain what is Reactor Pattern in Node.js?
- Node.js
Reveal answerHide answer
Reactor Pattern is an idea of non-blocking I/O operations in Node.js. This pattern provides a handler(in case of Node.js, a callback function) that is associated with each I/O operation. When an I/O request is generated, it is
submitted to a demultiplexer. This demultiplexer is a notification interface that is used to handle concurrency in non-blocking I/O mode and collects every request in form of an event and queues each event in a queue. Thus, the demultiplexer provides the Event Queue. At the same time, there is an Event Loop which iterates over the items in the Event Queue. Every event has a callback function associated with it, and that callback function is invoked when the Event Loop iterates.
- Question 107Expert
Why should you separate Express app and server?
- Node.js
Reveal answerHide answer
Keeping the API declaration separated from the network related configuration (port, protocol, etc) allows testing the API in-process, without performing network calls, with all the benefits that it brings to the table: fast testing execution and getting coverage metrics of the code. It also allows deploying the same API under flexible and different network conditions. Bonus: better separation of concerns and cleaner code. API declaration, should reside in app.js:
var app = express(); app.use(bodyParser.json()); app.use("/api/events", events.API); app.use("/api/forms", forms);Server network declaration, should reside in /bin/www:
var app = require('../app'); var http = require('http');/** * Get port from environment and store in Express. */ var port = normalizePort(process.env.PORT || '3000'); app.set('port', port);/** * Create HTTP server. */ var server = http.createServer(app); - Question 108Expert
Explain some Error Handling approaches in Node.js you know about. Which one will you use?
- Node.js
Reveal answerHide answer
Error handling in an asynchronous language works in a unique way and presents many challenges, some unexpected. There are four main error handling patterns in node: Error return value - doesn't work asynchronously
var validateObject = function (obj) { if (typeof obj !== 'object') { return new Error('Invalid object'); } };Error throwing - well-establish pattern, in which a function does its thing and if an error situation arises, it simply bails out throwing an error. Can leave you in an unstable state. It requires extra work to catch them. Also wrapping the async calls in try/catch won't help because the errors happen asynchronously. To fix this, we need domains. Domains provide an asynchronous try...catch.
var validateObject = function (obj) { if (typeof obj !== 'object') { throw new Error('Invalid object'); } }; try { validateObject('123'); } catch (err) { console.log('Thrown: ' + err.message); }Error callback - returning an error via a callback is the most common error handling pattern in Node.js. Handling error callbacks can become a mess (callback hell or the pyramid of doom).
var validateObject = function (obj, callback) { if (typeof obj !== 'object') { return callback(new Error('Invalid object')); } return callback(); }; validateObject('123', function (err) { console.log('Callback: ' + err.message); });Error emitting - when emitting errors, the errors are broadcast to any interested subscribers and handled within the same process tick, in the order subscribed.
var Events = require('events'); var emitter = new Events.EventEmitter(); var validateObject = function (a) { if (typeof a !== 'object') { emitter.emit('error', new Error('Invalid object')); } }; emitter.on('error', function (err) { console.log('Emitted: ' + err.message); }); validateObject('123'); Promises for async error handling doWork() .then(doWork) .then(doError) .then(doWork) .catch(errorHandler) .then(verify);Try...catch with async/await - ES7 Async/await allows us as developers to write asynchronous JS code that look synchronous.
async function f() { try { let response = await fetch('http://no-such-url'); } catch(err) { alert(err); // TypeError: failed to fetch } } f();Await-to-js lib - async/await without try-catch blocks in Javascript
import to from 'await-to-js'; async function main(callback) { const [err,quote] = await to(getQuote()); if(err || !quote) return callback(new Error('No Quote found'); callback(null,quote); } - Question 109Expert
What is the difference between process.nextTick() and setImmediate() ?
- Node.js
Reveal answerHide answer
The difference between process.nextTick() and setImmediate() is that process.nextTick() defers the execution of an action till the next pass around the event loop or it simply calls the callback function once the ongoing execution of the event loop is finished whereas setImmediate() executes a callback on the next cycle of the event loop and it gives back to the event loop for executing any I/O operations.
- Question 110Expert
Why do we need C++ Addons in Node.js?
- Node.js
Reveal answerHide answer
Node.js Addons are dynamically-linked shared objects, written in C++, that can be loaded into Node.js using the require() function, and used just as if they were an ordinary Node.js module. They are used primarily to provide an interface between JavaScript running in Node.js and C/C++ libraries. There can be many reasons to write nodejs addons:
- You may want to access some native apis that is difficult using JS alone.
- You may want to integrate a third party library written in C/C++ and use it directly in Node.js.
- You may want to rewrite some of the modules in C++ for performance reasons. N-API (pronounced N as in the letter, followed by API) is an API for building native Addons.
- Question 111Expert
What's the difference between pm2 and pm2-runtime and when to use one?
- Node.js Docker
Reveal answerHide answer
The main difference between pm2 and pm2-runtime is pm2-runtime is designed for Docker container which keeps an application in the foreground and keep the container running, pm2 is designed for normal usage where you send or run the application in the background. In simple words, the container's life is the life of CMD or entrypoint .
- Question 112Expert
Does JavaScript pass by references or pass by values?
- Node.js JavaScript
Reveal answerHide answer
Primitives are passed by value, and Objects are passed by copy of a reference. Specifically, when you pass an object (or array) you are (invisibly) passing a reference to that object, and it is possible to modify the contents of that object, but if you attempt to overwrite the reference it will not affect the copy of the reference held by the caller - i.e. the reference itself is passed by value:
function replace(ref) { ref = {}; // this code does _not_ affect the object passed } function update(ref) { ref.key = 'newvalue'; // this code _does_ affect the _contents_ of the object } var a = { key: 'value' }; replace(a); // a still has its original value - it's unmodfied update(a); // the _contents_ of 'a' are changed - Question 113Expert
What is the difference between cluster.fork() vs child_process.fork() in Node.js?
- Node.js
Reveal answerHide answer
There are a few main differences between cluster.fork() and child_process.fork() .
The child_process.fork() method is a bit lower-level and requires you to pass the location (file path) of the module as an argument, plus other optional arguments like the current working directory, the user that owns the process, environment variables, and more. Another difference is that cluster starts the worker execution from the beginning of the same module from which it ran. So if your app's entry point is index.js , but the worker is spawned in cluster-my-app.js , then it'll still start its execution from the beginning at index.js . child_process is different in that it spawns execution in whatever file is passed to it, and not necessarily the entry point of the given app. the cluster module actually uses the child_process module underneath for creating the children, which is done with child_process's own fork() method, allowing them to communicate via IPC, which is how port handles are shared among workers.
- Question 114Expert
How would you implement process communication when using cluster module in Node.js?
- Node.js
Reveal answerHide answer
The cluster module provides the process.message method to send a message to the master. With this, we able to listen to different messages from the app and send it to the relevant worker. Consider that example:
var cluster = require('cluster'); const numCPUs = require('os').cpus().length; module.exports.create = function (options, callback) { if (cluster.isMaster) { // fork child process for notif/sms/email worker global.smsWorker = require('child_process').fork('./smsWorker'); global.emailWorker = require('child_process').fork('./emailWorker'); global.notifiWorker = require('child_process').fork('./notifWorker');// fork application workers for (var i = 0; i < numCPUs; i++) { var worker = cluster.fork().process; console.log('worker started. process id %s', worker.pid); }// if application worker gets disconnected, start new one. cluster.on('disconnect', function (worker) { console.error('Worker disconnect: ' + worker.id); var newWorker = cluster.fork().process; console.log('Worker started. Process id %s', newWorker.pid); }); cluster.on('online', function (worker) { console.log('New worker is online. worker: ' + worker.id); // master receive messages and then forward it to worker based on type. worker.on('message', function (message) { switch (message.type) { case 'sms': global.smsWorker.send(message); break; // each of these worker is listning to process.on('message') // and then perform relevant tasks. case 'email': global.emailWorker.send(message); break; case 'notif': global.notifWorker.send(message); break; } }); }); } else { global.smsWorker = { send: function (message) { message.type = 'sms'; process.send(message); // send message to master console.log('sms Message sent from worker.'); } }; global.emailWorker = { send: function (message) { message.type = 'email'; process.send(message); // send message to master console.log('email Message sent from worker.'); } }; global.notifWorker = { send: function (message) { message.type = 'notif'; process.send(message); // send message to master console.log('notification Message sent from worker.'); } }; callback(cluster); } };