10 JavaScript Promise Challenges Before You Start an Interview | by bytefish | Jun, 2022

Whether you are an interviewee or an interviewer.

The Promise is the key feature of JavaScript asynchronous programming. Whether you love it or hate it, you have to understand it.

Here I’ve provided code challenges of Promise, from basic to advanced. There are 10 code snippets. And you should guess the output. Please try it yourself first before reading my analysis.

The first question is very simple.

We know:

  • Synchronized code blocks are always executed sequentially from top to bottom.
  • When we call new Promise(callback)the callback function will be executed immediately.

So this code is to sequentially output start, 1, end.

In this code snippet, a piece of asynchronous code appears. That is, the callback function in .then().

Remember, the JavaScript engine always executes synchronous code first, then asynchronous code.

When encountering this problem, we only need to distinguish between synchronous code and asynchronous code.

So the output is start , 1 , end and 2 .

This code is almost the same as the previous code; the only difference is that there is a console.log(3) after resolve(2).

Remember, the resolve method does not interrupt the execution of the function. The code behind it will still continue to execute.

So the output result is start , 1 , 3, end and 2 .

Because I have met some guys who think resolve will interrupt the execution of the function, I emphasize it here.

In this code, the resolve method has never been called, so promise1 is always in the pending state. So promise1.then(…) has never been executed. 2 is not printed out in the console.

So the output result is start , 1 , end .

This code deliberately adds a function to confuse challenges, and that is fn.

But please remember that no matter how many layers of function calls there are, our basic principles remain the same:

  • Execute synchronous code first, then asynchronous code
  • Synchronous code is executed in the order in which it was called

So the output result is start , middle, 1 , end and success.

Ok, do you think these challenges are easy?

In fact, these are just appetizers. The difficulty of Promise is that it appears with setTimeout. Next, our challenges will be even more difficult.

Are you ready? challengers!

Here Promise.resolve(1) will return a Promise object whose state is fulfilled and the result is 1 . It is synchronous code.

So the output result is start , end , 1 and 2.

Pay attention!

This is a very difficult question. If you can answer this question correctly and explain the reason, then your understanding of asynchronous programming in JavaScript has reached an intermediate level.

Before explaining this question, let us discuss the relevant theoretical basis.

We said before that the synchronous code is executed in the order of calling, so in what order are these asynchronous callback functions executed?

Some might say that whoever finishes first will execute first. Well, that’s true, but what if two async tasks complete at the same time?

For example, in the above code, the timer of setTimeout is 0 second, and Promise.resolve() will also return a fulfilled Promise object immediately after execution.

Both asynchronous tasks are completed immediately, so whose callback function will be executed first?

Some juniors may say that setTimeout is in front, so print setTimeout first, and then print resolve. Actually, this statement is wrong.

We know that many things are NOT performed in a first-in, first-out order, such as traffic.

We generally divide vehicles into two categories:

  • General vehicles
  • Vehicles for emergency missions. Such as fire trucks and ambulances.

When passing through crowded intersections, we will allow fire trucks and ambulances to pass first. Emergency vehicles have more priorities than other vehicles. Keywords: priorities.

In JavaScript EventLoop, there is also the concept of priority.

  • Tasks with higher priority are called microtasks. Includes: Promise, ObjectObserver, MutationObserver, process.nextTick, async/await .
  • Tasks with lower priority are called macrotasks. Includes: setTimeout , setInterval and XHR .

Although setTimeout and Promise.resolve() are completed at the same time, and even the code of setTimeout is still ahead, but because of its low priority, the callback function belonging to it is executed later.

So the output result is start , end , resolve and success.

This challenge is easy to complete if you already understand the previous code snippet.

We just need to do three steps:

  1. Find the synchronization code.
  2. Find the microtask code
  3. Find the macrotask code

First, execute the synchronization code:

Output 1 , 2 and 4 .

Then execute microtask:

But here is a trap: Since the current promise is still in the pending state, the code in this will not be executed at present.

Then execute macrotask:

And the state of the promise becoming to fulfilled .

Then, with Event Loop, execute the microtask again:

Before we introduce the priority between microtasks and macrotasks, here we look at the case of alternate execution of microtasks and macrotasks.

What is the output of this code?

Some may think microtask and macrotask like this:

  1. Execute all microtasks first
  2. Execute all macro tasks
  3. Execute all microtasks again
  4. cycle through

But the above statement is wrong.

The correct understanding is:

  1. Execute all microtasks first
  2. Execute a macrotask
  3. Execute all (newly added) microtasks again
  4. Execute next macrotask
  5. Cycle through

Just like this:

Or like this:

So in the above code, the callback function of Promise.then will be executed before the callback function of the second setTimeoutbecause it is a microtask and has been cut in line.

Well, this is our final challenge. If you can correctly say the output of this code, then your understanding of Promise is already very strong. And the same type of interview questions won’t bother you in any way.

This challenge is an upgraded version of the previous challenge, but the core principle remains the same.

Remember what we learned earlier:

  1. Sync code
  2. All microtasks
  3. First macro task
  4. All newly added microtasks
  5. Next macro task

So:

  1. Execute all sync code:

2. Execute all microtasks

3. Execute the first macro task

Note: In this step, the macrotask adds a new microtask to the task queue.

4. Execute all newly added microtasks

5. Execute the next macro task

So the output is this.

Leave a Comment