0

Code Snippet :

console.log('out1');
setTimeout(() => console.log('out2'), 0);
Promise.resolve('out3').then(console.log);
console.log('out4');

After executing I am getting the following :

"out1"
"out4"
"out3"
"out2"

As per my understanding, since Line 2 and line 3 both are asynchronous, so out2 should have been printed first as it is put into the queue first. But here it seems to be opposite.

"out1"
"out4"
"out2"
"out3"
  1. Can someone please explain what am I missing here.
  2. How does the line 3 in the code work just by passing a console.log

JSBin Link : https://jsbin.com/fafipezine/edit?js,console

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
roxid
  • 493
  • 4
  • 14
  • 1
    _"As per my understanding..."_ - Please add what you think happens so we can actually answer 1. – Andreas Jul 07 '21 at 08:01
  • 1
    _"How does the line 3..."_ - It's just a callback. `.then()` expects a function that will be executed. You pass it `console.log`. – Andreas Jul 07 '21 at 08:02
  • You could write it like this instead: `Promise.resolve('out3').then(x => console.log(x));` but that function simply passes its argument into console.log so you can just pass the console.log function itself. –  Jul 07 '21 at 08:05
  • 1
    As for 1., here's the [JS event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop). Your question seems to be why the Promise resolves before a zero delay timeout? Why did you expect the timeout to resolve first? Even a zero delay timeout is queued and processed "later" in the event loop, it'll just get its turn at the next possible moment. But after the Promise apparently. –  Jul 07 '21 at 08:07
  • @Andreas Can you please check now. – roxid Jul 07 '21 at 08:16
  • Aren't both of them asynchronous? So setTimeout should have been executed first? – roxid Jul 07 '21 at 08:19
  • `setTimeout`: _"If this parameter is omitted, a value of 0 is used, meaning execute "immediately", or more accurately, the next event cycle. Note that in either case, the actual delay may be longer than intended; see [Reasons for delays longer than specified](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#reasons_for_delays) below."_ – Andreas Jul 07 '21 at 08:20

2 Answers2

0

You can achive this by resolving promise in your setTimeout function:

console.log('out1');

new Promise((res) => {
  setTimeout(() => {
    console.log('out2');
    res("out3");
  }, 0);
}).then(console.log);

console.log('out4');

You can read about EventLoop in Javascript about these behaviors.

fayzzzm
  • 24
  • 3
  • Thanks for your answer but this is not exactly i am looking for. Just need the detailed reasoning behind it. – roxid Jul 07 '21 at 10:00
0

To answer your question, we need to shed light on how javascript executes code. Javascript follows the run to completion model, which pretty much means your code will reach the out4 console log no matter what (with an exception if you use async await in your code or an synchronous error occured etc.) Javascript uses the single threaded model, so how does it deal with code execution? To focus on your first question, we need to see how the task queue and microtask queue operates. Those queues are basically feeding the event loop with things to do. So, in which order they get consumed? The event loop consumes messages by first executing the current task and then proceeds to execute all microtasks that may be introduced and so on and so forth (check the tasks vs microtasks topic). So, what is a task and what is a microtask anyway? A task is created everytime code is requested to run, setTimeout or setInterval is called, or an event is fired (for example user input event) A microtask is very similar to a task, but they differ in the way they are created. Promises are basically using microtasks

To answer the first part of your question, there are two tasks. First task is to run this script. The second task that is enqueued is to fire the callback of setTimeout. Between those two tasks, two Promises (microtasks) are enqueued. All of the above result to the print order you see. There is a great visualization of the above in this blog post, which I highly recommend to read.

As per your second question, then function may use a function reference as an argument

rm_
  • 707
  • 5
  • 5