The Single-Threaded Deception
JavaScript executes in a single-threaded runtime model, meaning it has one call stack and one memory heap. However, the runtime host environment (Node.js, V8 in Chrome, or workerd in Cloudflare Workers) exposes asynchronous Web APIs backed by multi-threaded thread pools.
Microtasks vs. Macrotasks Execution Order
Consider this standard interview question:
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
Promise.resolve().then(() => {
console.log('3');
}).then(() => {
console.log('4');
});
console.log('5');
The output is strictly 1, 5, 3, 4, 2. Why?
console.log('1')executes synchronously.setTimeoutschedules a callback in the Macrotask Queue (timer phase).Promise.resolve()queues its callbacks into the Microtask Queue.console.log('5')executes synchronously.- Before the event loop picks the next macrotask, it drains the entire microtask queue to completion!