Can You Answer This Senior Level JavaScript Promise Interview Question?

Can You Answer This Senior Level JavaScript Promise Interview Question?
Photo by lamunix on Unsplash
3 mins read
13 Likes
331 Views

Most interviewees failed on it.

What is the output of the following code?

const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log("timerStart");
    resolve("success");
    console.log("timerEnd");
  }, 0);
  console.log(2);
});

promise.then((res) => {
  console.log(res);
});

console.log(4);

Write your answer in comment before reading analysis ✍️

Analysis

This question often stumps junior JavaScript developers because it tests the understanding of asynchronous behavior in JavaScript. To understand the output, we need to look at how JavaScript handles synchronous and asynchronous tasks.

Synchronous vs Asynchronous Code

JavaScript runs code in two modes: synchronous (executed immediately) and asynchronous (executed later, usually after some event, like a timer or a network request, has finished). The JavaScript event loop ensures that synchronous tasks are executed first, followed by any pending asynchronous tasks.

Example:

console.log('start');

const promise1 = new Promise((resolve, reject) => {
  console.log(1)
  resolve(2)
})
promise1.then(res => {
  console.log(res)
})
console.log('end');

In this code:

  1. console.log('start') runs first.
  2. Inside the promise, console.log(1) runs next.
  3. Then, the resolve(2) happens, but the .then() block is asynchronous, so it doesn't execute immediately.
  4. Finally, console.log('end') runs before the result from the promise (console.log(res)).

So, the output is:

start -> 1 -> end -> 2.

Microtasks vs Macrotasks

JavaScript divides asynchronous tasks into microtasks and macrotasks. Here's how they work:

  • Microtasks: These include promises. They are processed after the current synchronous code but before macrotasks.
  • Macrotasks: These include tasks like setTimeout(). They are processed after microtasks.

Understanding the Original Code

Let’s break down the original code with this knowledge:

const promise = new Promise((resolve, reject) => {
  console.log(1);                      // (1) Synchronous, logs 1
  setTimeout(() => {                   // (4) Asynchronous macrotask
    console.log("timerStart");         // (6) Logs "timerStart"
    resolve("success");                // (7) Resolves the promise
    console.log("timerEnd");           // (8) Logs "timerEnd"
  }, 0);
  console.log(2);                      // (2) Synchronous, logs 2
});

promise.then((res) => {
  console.log(res);                    // (5) Microtask, logs "success"
});

console.log(4);                        // (3) Synchronous, logs 4

Breakdown of Execution:

  1. The promise is created, and the executor function is run synchronously.
  2. console.log(1) runs (output: 1).
  3. The setTimeout() call schedules a macrotask, but this does not run immediately.
  4. console.log(2) runs (output: 2).
  5. promise.then() adds a microtask, which will run after all synchronous code finishes.
  6. console.log(4) runs (output: 4).
  7. Now that all synchronous code is done, the microtask (from promise.then()) runs (output: "success").
  8. Finally, the macrotask (from setTimeout()) runs. console.log("timerStart") (output: "timerStart"), the promise resolves, and console.log("timerEnd") runs (output: "timerEnd").

Final Output:

1
2
4
success
timerStart
timerEnd

Finally

This interview question tests the interviewee's understanding of the event loop, microtasks, and macrotasks in JavaScript. If you understand how JavaScript schedules asynchronous tasks, you'll be able to predict the output of this code with confidence.

Write your answer in comment box ☑️

Share:

Comments

0

Join the conversation

Sign in to share your thoughts and connect with other readers

No comments yet

Be the first to share your thoughts!