DEV Community

Cover image for Node.js Interview question: finite and infinite
Omi
Omi

Posted on

Node.js Interview question: finite and infinite

So recently, I was giving some interviews regarding Node.js and the interviewer asked me the below question:

The question: Refer to the codebase below and answer: what happens when we hit /infinite followed by a /finite?
Will the /finite gets stuck or will it return Hello World in response?

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

app.get("/infinite", (req, res) => {
  while (true) {}
  res.send("Never happens");
});

app.get("/finite", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

Enter fullscreen mode Exit fullscreen mode

Answer: It will get stuck.

The hint: Never block the main thread. This is the basic. But what does it really mean by not to block main thread?

To understand it, let's twist the above question a bit. Instead of putting a synchronous infinite loop, we put an asynchronous timeout of 10 seconds in the /infinite API. Now, the question is, will the finite API respond after 10 seconds or will it respond immediately?

Code:

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

const setTimeoutPromise = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Timer completed");
    }, 10000);
  });

app.get("/infinite", async (req, res) => {
  console.log("infinite");
  console.log("timestamp", new Date());
  // while (true) {}
  await setTimeoutPromise();
  res.send("executed after 10 seconds");
});

app.get("/finite", async (req, res) => {
  console.log("finite");
  console.log("timestamp", new Date());
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

Enter fullscreen mode Exit fullscreen mode

Answer: Now, the /finite responds immediately. After completing its 10 seconds, /infinite will respond with "executed after 10 seconds".

Reason: Javascript (V8 engine) runs the program in a single thread (aka main thread). Even if it is written inside an event listener or in a callback function of an async method (eg. fs.readFile("path/to/file", "", callback)). Node.js will put any Javascript synchronous code in the main thread.

while(true) {} is a synchronous code.

setTimeout is an asynchronous code. Simply means, the code requires OS resources (in this case -> timer). Since we have wrapped the setTimeout inside a promise and sending the response only after the promise is fulfilled, the main thread stalls the execution of /infinite function and make the main thread available. This is where the Node.js becomes non-blocking.

At this point, during the 10 seconds of the /infinite, any new event's (in this case, get call for /finite api) javascript code is ready to push into the main thread and execute.

After the timeout completes, the callback function mentioned inside the setTimeout will again come to the main thread for the javascript code execution.

Unfortunately, I could not find any sophisticated debugger that tells the developer that, hey! this is synchronous code, this is gonna block the main thread, or hey! this is a non-blocking code and your code will handle another request successfully!!!

Just have to read and practice through it, make cases by your own and understand between sync and async before jumping into the event-loop!

Follow up question:
If I modify the setTimeoutPromise like this:

const setTimeoutPromise = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Timer completed");
      while(true) {} // blocking it here lol! 
    }, 10000);
  });

Enter fullscreen mode Exit fullscreen mode

What happens to the finite call that is executed
1) between the 10 seconds
2) after 10 seconds?

Comment below!

Top comments (0)