What should be the output of this Javascript program having asynchronous operations?

Viewed 86

I'm expecting this code to run, then after 2 seconds, the execution stack will become empty and there is one callback of setTimeout. I'm expecting this as I would expect the message queue and the job queue to be empty(as the promise is not resolved yet).

So, the Callback is printed first, then after 3 seconds, the promise is resolved and its callback is placed in the job queue and the message Promise is resolved should be printed. But that is not what is happening. So what I am missing here?

The code is:

setTimeout(function() {
    console.log("Callbcack");
}, 0);
 
new Promise((resolve, reject) => {
    console.log("Inside promise");
    let ms = 5000 + new Date().getTime();
    while (new Date() < ms) {}
 
    resolve("Promise is resolved");
 
}).then((data) => {console.log(data)})
.catch((err) => {
    console.log(err);
})
 
var ms = 2000 + new Date().getTime();
while (new Date() < ms) {}
2 Answers

You have just discovered JavaScript's microtasks. In short, there is actually two different callback queues. One for the microtasks and one for the macrotasks. In your case, the callback of your Promise is a microtask, while the setTimeout callback is a macrotask. The microtasks queue is always handled before the macrotasks queue.

So, even if you queued function() { console.log("Callbcack"); } before (data) => { console.log(data) }, the second one will always execute first, no matter how long you block the thread before resolving the Promise, because both queues will be handled when the top-level code has finished executing.

Promise executor function is run synchronously (precisely at the time you call new Promise(executor)) so promise is resolved within running the top level code (at the initial stack) after 5000 ms.

Then, microtask queue is executed, so you see result of console.log(data).

Then, js (event loop) is free to run the next asynchronous piece which happen to be the timer handler.

Related