Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execution order of Timeout and Promise functions(Main Tasks and Micro Tasks)

Tags:

javascript

I was browsing the html5boilerplate github and I went to see some of the interview questions and I came across this one and I don't understand why it outputs in the order it does. I assumed it would be one four two three not the output it does. Can someone explain why? sorry if it's too simplistic.

Question: What does the following code print?

console.log('one');
setTimeout(function() {
  console.log('two');
}, 0);
Promise.resolve().then(function() {
  console.log('three');
})
console.log('four');

The output was in this order "one" "four" "three" and finally "two"

Code Snippet

console.log('one');
setTimeout(function() {
  console.log('two');
}, 0);
Promise.resolve().then(function() {
  console.log('three');
})
console.log('four');
like image 628
Nen Avatar asked Aug 07 '18 14:08

Nen


2 Answers

I think output one and four are pretty clear. setTimeout is a part of Main Task queue while Promise is of Micro task queue that's why "three" and finally "two" is printed.

Step by Step execution is as below:

  1. When script is executed, console.log(“one”) is executed first.

  2. When setTimeout(…) is encountered, runtime initiates a timer, and after 0ms. Callback function() {} of setTimeout(…) is queued in Task queue.

  3. When promise object is encountered, its callback i.e function() {} is queued in Micro task queue.

  4. Finally, it executes last console.log(“four”) .

According to standard specification

  1. Once a call stack is emptied, it will check Micro task queue and finds callback function() {} of promise.Call stack will execute it (logs three).

  2. Once again, call stack is emptied after processing callbacks in Micro task queue. Finally, event loop picks up a new task from the Task queue i.e callback function() {} of setTimeout(…) ( logs two) execute it.


Visual Image

Visual Image

console.log('one');
setTimeout(function() {
  console.log('two');
}, 0);
Promise.resolve().then(function() {
  console.log('three');
})
console.log('four');
like image 114
NullPointer Avatar answered Oct 18 '22 13:10

NullPointer


This is due to the JS call stack; both setTimeout and Promise.resolve().then are asynchronous calls.

setTimeout(function(){...}, 0) simply queues the code to run once the current call stack is finished executing, exactly the same as Promise.resolve().then() (albeit to a subqueue). The subqueue finishes executing hence why three appears before two, and then the main queue is finished, so setTimeout can now be called.

like image 25
BenM Avatar answered Oct 18 '22 12:10

BenM