What is the event loop?
The event loop is a mechanism that allows JavaScript to execute asynchronous code in a single-threaded environment. It works by constantly checking two queues: the microtask queue and the macrotask queue. These queues store the callbacks of the asynchronous operations that are waiting to be executed.
setTimeout(function() {
console.log("Hello after 3 seconds");
}, 3000);
The callback function in this example will be executed after 3 seconds, but not immediately. It will be placed in the macrotask queue, and will wait for its turn to run.
What is the difference between microtask and macrotask queue?
The main difference between microtask and macrotask queue is their priority. The event loop always gives higher priority to the microtask queue, and will process all the callbacks in the microtask queue before moving on to the macrotask queue.
The microtask queue contains the callbacks of operations that are considered more urgent or important, such as promises and mutation observers APIs.
The macrotask queue contains the callbacks of operations that are less urgent such as timers, I/O events, and user interface events.
console.log("Start");
setTimeout(function() {
console.log("Timeout");
}, 0);
Promise.resolve().then(function() {
console.log("Promise"); // microTask!
});
console.log("End");
What do you think will be the output of this code? You might expect it to be:
Start -> Timeout -> Promise -> End
But actually, it will be:
Start -> End -> Promise -> Timeout
Let's decode step by step:
Because the callback of setTimeout
is placed in the macrotask queue, while the callback of Promise.resolve
is placed in the microtask queue.
- The event loop will first execute the synchronous code (console.log("Start") and console.log("End"))
- Then it will check the microtask queue and execute all the callbacks there (console.log("Promise"))
- Then it will check the macrotask queue and execute one callback there (console.log("Timeout")).
Why to know the difference is important?
Understanding the difference between microtask and macrotask queue can help you write better asynchronous code in JavaScript. It can help you avoid some common mistakes such as:
- Blocking the event loop by creating too many microtasks or long-running microtasks. This can cause performance issues and delay other important tasks.
- Creating race conditions or unexpected results by relying on the order of execution of different types of tasks. For example, if you use setTimeout to schedule some code after a promise, you cannot guarantee that the promise will resolve before the timeout.
- For example, if you use setTimeout with a delay of 0 milliseconds to defer some code execution, you might miss some events that happen in between.
To avoid these mistakes follow some best practices, such as:
- Use promises or async/await instead of callbacks whenever possible. Promises are easier to read, write, and debug than nested callbacks. They also allow you to handle errors more easily.
- Use queueMicrotask instead of setTimeout with a very small delay. These methods are more reliable and efficient than setTimeout, as they schedule a microtask without any delay.
Conclusion
I hope this article helped you understand the difference between microtask and macrotask queue in the event loop. Checkout my easy to understand article on Debounce and Throttling in JS 🚀
Top comments (3)
fetch also returns a promise how will it be handled, in microtask queue or macrotask queue?
Since it's a promise, it will be handled by the microtask queue.
Correct, my question was same. Is this incorrectly mentioned in this article !