What's the difference between the call stack, event loop, task queue, and microtask queue in JavaScript? [closed]

What's the difference between the call stack, event loop, task queue, and microtask queue in JavaScript? [closed]

Sure! Here's an expanded version of the theory-based async question body that meets the 220-character minimum for Stack Overflow:


Body:

I'm trying to get a deeper understanding of how JavaScript handles asynchronous behavior. I often hear about the call stack, event loop, task queue (aka callback queue), and microtask queue, especially when dealing with things like setTimeout, Promises, and async/await.

I get that JavaScript is single-threaded and uses the event loop to manage asynchronous code, but I donโ€™t fully understand how these parts interact. Specifically:

  • What exactly is the difference between the task queue and microtask queue?
  • Why does a Promise.then() run before a setTimeout() even when both are async?
  • How do async/await and Promise chains fit into the microtask queue?
  • In what order are these executed when mixed together?

A clear breakdown of how these pieces work together (especially with an example or timeline) would be really helpful. I want to write more predictable asynchronous code and avoid hidden timing issues. Thanks!

Answer

๐Ÿ”น Call Stack: This is where JavaScript runs your synchronous code. Functions get pushed in when called, and popped out when done.

๐Ÿ”น Event Loop: A mechanism that constantly checks the Call Stack. If itโ€™s empty, it looks at the Microtask Queue first, and then the Task Queue to pick what to run next.

๐Ÿ”น Task Queue (aka Callback Queue): Holds async callbacks from things like setTimeout, setInterval, and DOM events. These are run after the Call Stack is empty and after all Microtasks are done.

๐Ÿ”น Microtask Queue: Used by Promises, async/await, and other APIs like queueMicrotask(). Microtasks run immediately after the current call stack is empty, and before any tasks in the Task Queue.

๐Ÿ”ธ Why does Promise.then() run before setTimeout()? Because Promises are added to the Microtask Queue, which has higher priority than the Task Queue. Even setTimeout(..., 0) will wait until all Microtasks are done.

๐Ÿ”ธ How do async/await and Promises fit in? An await pauses the async function. The code after the await is placed in the Microtask Queue, just like a .then() callback.

๐Ÿ”ธ Execution Order can be like :

 console.log("Start");

setTimeout(() => {
  console.log("setTimeout");
}, 0);

Promise.resolve().then(() => {
  console.log("Promise");
});

console.log("End");

Output:

javascript
Copy
Edit
Start
End
Promise
setTimeout

1- Start โ†’ sync

2- setTimeout scheduled โ†’ goes to Task Queue

3- Promise.then โ†’ goes to Microtask Queue

4- End โ†’ sync

5- Microtasks run โ†’ prints Promise

6- Task Queue runs โ†’ prints setTimeout

๐Ÿ”ธ Async/Await Example:

async function test() {
  console.log("A");
  await Promise.resolve();
  console.log("B");
}

test();
console.log("C");

Output:

A
C
B
  • A is synchronous

  • B is in the Microtask Queue (after await)

  • So C prints before B

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles