2
function job(){
    sequenceB()
    sequenceC()
}

function sequenceB(){
    setTimeout(_ => console.log(` Timeout at B`), 0);
    Promise.resolve().then(_ => console.log(' Promise at B'));
}

function sequenceC(){
    setTimeout(_ => console.log(` Timeout at C`), 0);
    Promise.resolve().then(_ => setTimeout(console.log(' Promise at C'), 1000));
}
job();

what will be the print order here and why? I seem to get the output in this order Promise at B, Promise at C, Timeout at B, Timeout at C

tested this on both chrome(latest version) and edge(latest version)

  • IIRC microtask resolution happens before the next tick of the event loop, i.e. before `setTimeout` runs. – Jared Smith Mar 13 '23 at 16:27
  • Promises belong to what is known as the job queue and this has a higher preference than the callback queue which is where the setTimeout is waiting to be put on the callstack by the the event loop – dbzx10299 Mar 13 '23 at 16:32
  • 1
    This is probably a good resource if you're not into thumbing through the spec https://www.youtube.com/watch?v=cCOL7MC4Pl0 – Jared Smith Mar 13 '23 at 16:33
  • See also this https://stackoverflow.com/a/30910084/3757232 – Jared Smith Mar 13 '23 at 16:38
  • 1
    Did you mean? `setTimeout(() => console.log(' Promise at C'), 1000)` because now it does nothing – Konrad Mar 13 '23 at 16:39
  • I assumed it will be this: Promise at B Timeout at B This is because the job calls sequenceB first, sets up a setTimeout for printing ' Timeout at B' and schedules a promise to print ' Promise at B'. it's resolved immediately. then the timeout at B should fire. or so I thought. how come it prints the promise at C before the timeout at B? @JaredSmith I watched this video and I am still puzzled. – Ephraim XYZ Mar 13 '23 at 16:39
  • 1
    @EphraimXYZ because *all* the microtasks (think queued up Promise callbacks) have to resolve before the next macrotask is handled (and the callbacks queued up by `setTimeout` are macrotasks). So every tick of the event loop exactly one setTimeout callback will run but potentially hundreds of Promise.then callbacks will. I will grant you it's complicated but that's really what it boils down to. – Jared Smith Mar 13 '23 at 16:42
  • Your code has a typo which makes it more confusing than necessary. As already spotted by @Konrad, in `Promise.resolve().then(_ => setTimeout(console.log(' Promise at C'), 1000));` the `setTimeout` is not used, the `console.log` call is made immediately in the promise callback. – Kaiido Mar 13 '23 at 23:25

1 Answers1

2

When you call job(), sequenceB() is called, then sequenceC() is called. When sequenceB() runs setTimeout(_ => console.log(' Timeout at B'), 0); will be pushed to the callback queue and Promise.resolve().then(_ => console.log(' Promise at B')); will be pushed to the job queue. Then the execution starts for sequenceC(). The same happens again, setTimeout(_ => console.log(' Timeout at C'), 0); is pushed to the callback queue and Promise.resolve().then(_ => setTimeout(console.log(' Promise at C'), 1000)); is pushed to the job queue.

Now the event loop says hey, is the job/microtask empty? And it's not, so that code gets executed, which is the promise from the sequenceB() function, then it checks the job queue again, and it finds the other promise.

The next time around, it looks and the job/microtask queue is empty so then it looks at the callback queue and there is your setTimeout callback, so that gets pushed to the call stack. Once that executes, the event looks again and sure enough there is another setTimeout callback there. This is again executed and the process repeats.

With that being said the output is:

// from the microtask queue
 Promise at B
 Promise at C

// from the callback queue
 Timeout at B
 Timeout at C
dbzx10299
  • 722
  • 2
  • 14
  • So what you're saying is that it go through all the functions and logs everything, then does the 'round' of the microtasks, and then and only then will it carry out the microtasks and then tasks, as I was able to confirm by changing the job() function to this: ``` function questionE(){ sequenceB(); console.log('mid'); sequenceC(); } ``` output was 'mid' , ' Promise at B', ' Promise at C', ' Timeout at B', ' Timeout at C' Thank you. – Ephraim XYZ Mar 13 '23 at 16:48
  • If I was you I would research the callstack a bit, that will make things clearer. – dbzx10299 Mar 13 '23 at 16:50
  • Any specific source comes to mind? @dbzx10299 – Ephraim XYZ Mar 13 '23 at 16:54
  • Yea just google asynchronous js and callstack with medium, e.g. asynchronous js explained medium, there's a lot of good blog posts – dbzx10299 Mar 13 '23 at 17:24