The event loop in JavaScript is what allows it to handle asynchronous operations in a single-threaded environment.
It constantly checks if the call stack is empty and then pushes callbacks from different queues into it to be executed.
🧠 Basic Flow:
- All synchronous code runs first in the call stack.
- When async code (like
setTimeoutor Promises) finishes, its callback goes into a task queue. - The event loop checks if the stack is empty — if yes, it pushes tasks from the queue into the stack to execute.
🪄 Macrotasks vs Microtasks
- Macrotasks: These include callbacks from
setTimeout,setInterval,setImmediate, and DOM events. - Microtasks: These include callbacks from Promises (
.then,catch,finally) andqueueMicrotask().
👉 The event loop always processes all microtasks first before moving to the next macrotask.
🧾 Example:
console.log("Start");
setTimeout(() => {
console.log("Macrotask");
}, 0);
Promise.resolve().then(() => {
console.log("Microtask");
});
console.log("End");
🟡 Output:
Start
End
Microtask
Macrotask
✅ Why?
- Synchronous code → runs first.
- Microtasks (Promise) → run after the stack is empty.
- Macrotasks (setTimeout) → run after all microtasks finish.
In short:
- Event loop manages execution between stack and queues.
- Microtasks have higher priority than macrotasks.
- This is why Promises often resolve before
setTimeoutcallbacks, even with zero delay.