Node JS Interview Questions

Node JS Interview Questions

What is Node JS?

Node.js is an open-source, server-side JavaScript runtime environment that allows developers to run JavaScript code on the server. It is built on the V8 JavaScript engine, which is developed by Google for use in web browsers. Node.js enables non-blocking, event-driven architecture, making it well-suited for building highly scalable and efficient network applications.

  1. Non-Blocking I/O: Node.js is known for its ability to handle many concurrent connections without blocking the execution of other code. This enables efficient handling of I/O operations, such as reading and writing to files, making network requests, and accessing databases.

  2. Event-Driven Architecture: Node.js uses an event-driven, asynchronous model, where it listens for events and triggers associated callback functions when events occur. This design pattern is essential for handling concurrent connections and real-time applications.

Why use Node JS?

  • Node js enables consistent use of Javascript for both server-side and client-side development

  • Node js efficiently handles numerous concurrent connections without blocking, making it ideal for I/O-intensive tasks

  • It gives High Performance

  • It is Highly Scalable

  • It can excel in creating low-latency real-time applications like chat and online gaming.

Cons of using Node JS

  • Single-Threaded: Node.js is single-threaded, which means it might not be the best choice for CPU-intensive tasks.

  • Callback Hell: When handling many asynchronous operations, Node.js code can become deeply nested with callbacks, leading to the "Callback Hell" or "Pyramid of Doom" issue. This can affect code readability and maintainability.

  • Not Ideal for Heavy Computation: If your application requires heavy computational tasks, Node.js might not be the best choice due to its single-threaded nature. Other languages like Python or Java might be more suitable.

How does Node JS work?

Node.js is built on an event-driven, non-blocking architecture. It uses an event loop to manage and prioritize tasks. When a function is called, it's added to the call stack, executed, and removed. For non-blocking operations, like I/O tasks, Node.js initiates them and continues processing other tasks while they're in progress. Callback functions handle the results of these asynchronous operations and are placed in the event queue. The event loop continuously checks the event queue for pending callbacks and processes them, allowing Node.js to efficiently handle multiple tasks without blocking the entire process. This makes it highly suitable for real-time applications and APIs, as well as I/O-intensive tasks.

Why Node JS is single-threaded?

A single-threaded process is the execution of programmed instructions in a single sequence, A single-threaded architecture simplifies the development and debugging process. There are no concerns about thread synchronization or race conditions making it easier for developers to reason about their code.

What is npm?

npm stands for Node Package Manager, responsible for managing all the packages and modules of Node JS, If provides two main functionality

  • Provides online repositories for Node JS packages/modules

  • Provides command line utility to install Node JS packages and also manages Node JS versions and dependencies

What are modules in Node JS?

Modules in Node.js serve as self-contained units that encapsulate functionality, making them reusable across different parts of an application.

There are two types of Modules Internal and External, There are various external modules that can be installed in a node application through npm available on the internet, Some of the important internal modules are mentioned below

  1. path

     const path = require('path')
    
     //base file name
     console.log(path.basename(__filename))
    
     //directory name
     console.log(path.dirname(__filename))
    
     //file extension
     console.log(path.extname(__filename))
    
     //Create path object
     console.log(path.parse(__filename))
    
     //Concatenate paths
     console.log(path.join(__dirname,'test','hello.html'))
    
  2. fs

const fs = require("fs");
const path = require("path");
//for creating folder
// path, options,callback
fs.mkdir(path.join(__dirname, "/test"), {}, (err) => {
  if (err) {
    throw err;
  }
  console.log("Folder created");
});

//for creating file
// path, options,callback
fs.writeFile(
  path.join(__dirname, "/test", "hello.txt"),
  "Hello World",
  (err) => {
    if (err) {
      throw err;
    }
    console.log("Folder Written...");
    fs.appendFile(
        path.join(__dirname, "/test", "hello.txt"),
        " I love node js",
        (err) => {
          if (err) {
            throw err;
          }
          console.log("Folder Written...");
        }
      );
  }
);

//Read File
fs.readFile(path.join(__dirname,'/test','hello.txt'),'utf-8',(err,data)=>{
    if (err) {
        throw err;
    }
    console.log(data);
})

//Rename File
fs.rename(
    path.join(__dirname,'/test','hello.txt'),
    path.join(__dirname,'/test','helloWorld.txt'),
    err =>{
        if (err) {
            throw err;
        }
        console.log("File renamed...")
    }
)
  1. os

const os = require("os")
//platform
console.log(os.platform())
//architecture
console.log(os.arch())
//CPU core info
console.log(os.cpus())
//free memory
console.log(os.freemem())
//total memory
console.log(os.totalmem());
//home dir
console.log(os.homedir())
//up time
console.log(os.uptime())
  1. URL

const url = require("url");
const myUrl = new URL("http://mywebsite.com/hello.html?id=100&status=active")
//Serialized URL
console.log(myUrl.href)
//Host root  domain
console.log(myUrl.host)
//Hostname does not get host
console.log(myUrl.hostname)
//path name
console.log(myUrl.pathname)
//Serialized query
console.log(myUrl.search)
//Params object
myUrl.searchParams.append('abc','123')
console.log(myUrl.search3Params)
  1. HTTP

const http = require("http");

http.createServer((req,res)=>{
    res.write("Hello World");
    res.end();
}).listen(5000,()=>console.log("Server is running"));

Emitters in Node JS

const EventEmitter = require('events');

// Create a custom event emitter for the notification system
class NotificationSystem extends EventEmitter {}

// Instantiate the custom event emitter
const notificationEmitter = new NotificationSystem();

// Function to send a notification to a customer
function sendNotification(customer, product) {
  console.log(`Notifying ${customer} that ${product} is back in stock.`);
}

// Register a custom event for product availability
notificationEmitter.on('productAvailable', (customer, product) => {
  sendNotification(customer, product);
});

// Simulate a product coming back in stock
const product = 'Example Product';
const interestedCustomers = ['Customer1', 'Customer2', 'Customer3'];

for (const customer of interestedCustomers) {
  // Emit the 'productAvailable' event for each interested customer
  notificationEmitter.emit('productAvailable', customer, product);
}

Creating a Server completely using Node JS

const http = require("http");
const path = require("path");
const fs = require("fs");

const server = http.createServer((req, res) => {
  // Handle the root URL ("/")
  if (req.url === "/") {
    fs.readFile(
      path.join(__dirname, "public", "index.html"),
      (err, content) => {
        if (err) {
          throw err;
        }
        res.writeHead(200, { "Content-Type": "text/html" });
        res.end(content);
      }
    );
  } else if (req.url === "/about") {
    fs.readFile(
      path.join(__dirname, "public", "about.html"),
      (err, content) => {
        if (err) {
          throw err;
        }
        res.writeHead(200, { "Content-Type": "text/html" });
        res.end(content);
      }
    )
  } else if (req.url === "/api/users") {
    const users = [
      { name: "Avez", age: 20 },
      { name: "John", age: 50 },
    ];
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify(users));
  } else {
    // Serve static files (JavaScript, CSS, images)
    const filePath = path.join(__dirname, "public", req.url);
    const extname = path.extname(filePath);

    // Set the content type based on the file extension
    let contentType = "text/html";
    switch (extname) {
      case ".js":
        contentType = "text/javascript";
        break;
      case ".css":
        contentType = "text/css";
        break;
      case ".jpg":
        contentType = "image/jpeg";
        break;
      case ".png":
        contentType = "image/png";
        break;
    }

    fs.readFile(filePath, (err, content) => {
      if (err) {
        if (err.code === "ENOENT") {
          // Page not found
          fs.readFile(
            path.join(__dirname, "public", "404.html"),
            (err, content) => {
              res.writeHead(404, { "Content-Type": "text/html" });
              res.end(content, "utf8");
            }
          );
        } else {
          // Server error
          res.writeHead(500);
          res.end(`Server Error: ${err.code}`);
        }
      } else {
        // Serve the file
        res.writeHead(200, { "Content-Type": contentType });
        res.end(content);
      }
    });
  }
});

const PORT = 5000;

server.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

What is package.json

The package.json file in Node JS is the heart of the entire application, This file holds the metadata for a particular project

What is a callback hell?

Callback hell, also known as the Pyramid of Doom, refers to a situation in JavaScript and Node.js where code becomes deeply nested and difficult to read and maintain due to the excessive use of callbacks, especially in asynchronous operations. It typically occurs when you have multiple asynchronous tasks that depend on the results of previous tasks, leading to a chain of nested callbacks. The code structure ends up looking like a pyramid or a series of nested blocks.

Explain the concept of middleware

Middleware is a function that receives the request and response objects. Most task that middleware function perform are

  • Executing any code, update or modify the request and response object

  • Finish the request-response cycle

  • Invoke the next middleware in the stack

const express = require('express');
const app = express();
const port = 3000;

// Define a custom middleware function
const requestLogger = (req, res, next) => {
  // Log information about the incoming request
  console.log(`[${new Date().toLocaleString()}] ${req.method} request to ${req.url}`);

  // Continue to the next middleware or route handler
  next();
};

// Use the custom middleware for all routes
app.use(requestLogger);

// Define a simple route
app.get('/', (req, res) => {
  res.send('Hello, Express!');
});

// Start the Express server
app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});

When you run this code, the requestLogger middleware will log details of every incoming HTTP request to the console, providing a simple example of how middleware can intercept and process requests in an Express.js application.

if you want to achieve similar functionality without used middleware then we have to handle request logging and routing directly with our route handlers

const express = require('express');
const app = express();
const port = 3000;

// Define a route for the root path ("/")
app.get('/', (req, res) => {
  // Log information about the incoming request
  console.log(`[${new Date().toLocaleString()}] ${req.method} request to ${req.url}`);

  // Respond with a message
  res.send('Hello, Express!');
});

// Define a route for the "/about" path
app.get('/about', (req, res) => {
  // Log information about the incoming request
  console.log(`[${new Date().toLocaleString()}] ${req.method} request to ${req.url}`);

  // Respond with a message
  res.send('About Us');
});

// Define a route for the "/contact" path
app.get('/contact', (req, res) => {
  // Log information about the incoming request
  console.log(`[${new Date().toLocaleString()}] ${req.method} request to ${req.url}`);

  // Respond with a message
  res.send('Contact Us');
});

// Start the Express server
app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});

What is REPL

Read: Read the user input

Evaluate: Receives and evaluates the input

Print: Print the final result

Loop: Loop the provided command until CTRL + C is pressed twice

What are streams in Node JS

Streams are objects that enable you to read data or write data continuously

There are four types of Streams

Readable Streams:

  • Readable streams are used for reading data from a source. Common sources include files, HTTP requests, and data generated in memory.

Writable Streams:

  • Writable streams are used for writing data to a destination. Common destinations include files, network sockets, or HTTP responses.

Duplex Streams:

  • Duplex streams are both readable and writable. They are often used for communication, where data can be both sent and received simultaneously.

Transform Streams:

  • Transform streams are a subset of duplex streams that allow for data transformation during the read or write process. They are often used to modify data as it flows from a source to a destination.

What are two types of API functions in Node JS

Synchronous (Blocking) API Functions:

  • Synchronous API functions block the execution of your code until the operation is completed. They wait for the operation to finish and return the result immediately.

      const fs = require('fs');
      const data = fs.readFileSync('example.txt', 'utf8');
      console.log(data);
    

Asynchronous (Non-Blocking) API Functions:

Asynchronous API functions do not block the execution of your code. Instead, they initiate the operation and immediately return control to your code, allowing it to continue executing other tasks.

const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.error(err);
  } else {
    console.log(data);
  }
});

What is libuv

libuv is a core component of Node.js that provides an event loop and platform-independent abstractions for handling asynchronous I/O operations. It allows Node.js to efficiently manage tasks like reading files, making network requests, and handling timers

What is the purpose of NODE_ENV

NODE_ENV is an environment variable used in Node.js to determine the runtime environment of an application. It helps developers and applications to adapt behavior based on whether they are running in a development, production, or other environment.

Can DOM be accessed in Node JS?

DOM cannot be accessed in node js . DOM is a browser-specific API that allows for the manipulation of HTML or XML documents, Since Node JS does not run in a browser it does not have access to DOM

What is ESlint?

ESLint stands for ECMAScript Lint. The name reflects its role as a tool for linting (analyzing and identifying issues in) ECMAScript or JavaScript code.

What is a Passport in Node JS?

Passport is a popular authentication middleware for Node JS, Passport supports many authentication mechanisms, including username/password,social logging like Facebook, Google and JWT

Does Node JS provide any debugger?

Yes Node JS provides a built-in debugger called Node JS inspector and is accessed using inspect or inspect-brk flags when you use Node JS application

Is Cryptography supported in Node JS?

Yes Node JS provides built-in support for cryptography through the crypto module

Why does Google use the V8 engine for Node JS?

Google uses the V8 engine. It is Chrome runtime engine that converts Javascript code into native machine code, Its speeds up the application execution and response process and gives you a fast running applications