Trace the fixed program
The trace starts with start. Schedule a promise reaction, then queueMicrotask, then append end synchronously. The final promise reaction prints the completed trace.
const trace=['start'];
Promise.resolve().then(()=>trace.push('promise'));
queueMicrotask(()=>trace.push('microtask'));
trace.push('end');
Promise.resolve().then(()=>console.log(JSON.stringify(trace)));
["start","end","promise","microtask"]| Execution stage | Added value | Trace at that point |
|---|---|---|
| Synchronous body | start, end | ["start","end"] |
| First queued reaction | promise | ["start","end","promise"] |
| Explicit microtask | microtask | ["start","end","promise","microtask"] |
Explain the result
The synchronous body finishes before these queued callbacks run. In this supplied sequence the promise reaction is enqueued before the explicit microtask. The printing reaction follows both. This observes queue order, not elapsed time or scheduling across unrelated tasks and hosts.
Test the alternative
Reading a flag immediately after .then sees false even on an already fulfilled promise. A later reaction sees true.
let ran=false;Promise.resolve().then(()=>{ran=true;});const immediate=ran;
Promise.resolve().then(()=>console.log(JSON.stringify({immediate,later:ran})));
{"immediate":false,"later":true}Work the boundary case
If queueMicrotask is scheduled first, what changes?
Show the worked answer
The two queued labels swap. start and end still precede both in this program.
const trace=['start'];queueMicrotask(()=>trace.push('microtask'));Promise.resolve().then(()=>trace.push('promise'));trace.push('end');
Promise.resolve().then(()=>console.log(JSON.stringify(trace)));
["start","end","microtask","promise"]