JavaScript Notes
Master JavaScript
Introduction
The callback queue (also called the macrotask queue or task queue) is a waiting area where asynchronous callbacks sit until the call stack is empty. When a timer expires, a network request completes, or a DOM event fires, the browser doesn't immediately run the callback — it places it in the callback queue first.
Understanding the callback queue is essential because it explains:
- Why
setTimeout(fn, 0)doesn't run immediately - Why synchronous code always runs before async callbacks
- How the event loop decides what to run next
- Why Promises run before
setTimeoutcallbacks
How the Callback Queue Works
The key rules:
- Web APIs complete async work, then push callbacks to the callback queue
- The event loop checks: is the call stack empty? Are microtasks empty?
- Only then does it take ONE callback from the callback queue and push to stack
- After that callback finishes, check microtasks again, then take next macrotask
FIFO Order — First In, First Out
The callback queue is a FIFO structure — callbacks are processed in the order they were added.
Synchronous code (runs before ALL callbacks) Callback 1 (added first) Callback 2 (added second) Callback 3 (added third)
Callback Queue State (FIFO):
Step-by-Step Execution Tracing
1. Start 2. End 3. Promise microtask 4. setTimeout 0ms 5. setTimeout 100ms
Detailed Execution Timeline:
Callback Queue vs Microtask Queue
This is critical for understanding execution order. Microtasks always run before macrotasks (callback queue items).
SYNC: start SYNC: end MICROTASK: Promise 1 MICROTASK: queueMicrotask MICROTASK: Promise 2 (nested) MACROTASK: setTimeout
Priority Comparison Table:
Important: After each macrotask, the event loop drains ALL pending microtasks before picking the next macrotask.
What Puts Things in the Callback Queue?
1. setTimeout / setInterval
Interval tick 1 Interval tick 2 Timer callback in queue Interval tick 3
2. Event Handlers (DOM Events)
3. I/O Callbacks (Node.js)
4. Network Callbacks (XMLHttpRequest)
const xhr = new XMLHttpRequest();
xhr.onload = function() {
// This callback enters the queue when the network request completes
console.log("XHR callback:", xhr.responseText.substring(0, 50));
};
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts/1");
xhr.send();Timer Accuracy — Why setTimeout(fn, 0) Is Never Truly 0ms
Sync work done: 4999999950000000 Ran after ~150ms (specified 0ms) ← delayed by sync work!
Common Mistakes ⚠️
Mistake 1: Expecting setTimeout(fn, 0) to Run Immediately
before after timeout
Mistake 2: Blocking the Callback Queue with Heavy Sync Work
Mistake 3: Confusing Callback Queue Priority with Microtasks
I'm actually first! I thought I'd be first!
Promises use the microtask queue, which has higher priority than the callback queue.
Interview Questions 🎯
Q1. What is the callback queue in JavaScript?
The callback queue (also called the macrotask queue or task queue) is a FIFO data structure where asynchronous callbacks wait until the call stack is empty. Callbacks fromsetTimeout,setInterval, DOM event handlers, and I/O operations are placed here when they're ready to run. The event loop moves one callback at a time from this queue to the call stack.
Q2. What is the difference between the callback queue and the microtask queue?
The microtask queue has higher priority and is drained completely after each synchronous task before any macrotask (callback queue item) runs. Microtasks include Promise callbacks (then,catch,finally) andqueueMicrotask(). The callback queue processes one item per event loop cycle, after all microtasks are exhausted.
Q3. Why does setTimeout(fn, 0) not run immediately?
setTimeout(fn, 0) schedules the callback in the Web API with a minimum delay of 0ms, but the callback is placed in the callback queue and can only run when: (1) the timer has expired, (2) the call stack is empty, and (3) all microtasks have been drained. If synchronous code is running, the callback waits.Q4. Is the callback queue FIFO or LIFO?
The callback queue is FIFO (First In, First Out) — callbacks are processed in the order they enter the queue. This is the opposite of the call stack, which is LIFO.
Q5. What puts callbacks into the callback queue?
Web APIs put callbacks into the queue after completing their work: timers (setTimeout,setInterval), network requests (XMLHttpRequest, fetch), DOM event handlers, I/O operations in Node.js, andMessageChannelmessages.
Q6. How many macrotasks does the event loop process per cycle?
One. After each macrotask completes, the event loop drains all pending microtasks, allows a browser render if needed, then picks the next macrotask. This ensures UI stays responsive.
Q7. Can microtasks starve macrotasks?
Yes! If microtasks keep generating new microtasks infinitely, macrotasks (and browser rendering) are blocked forever. For example: function addMicrotask() { Promise.resolve().then(addMicrotask); } addMicrotask(); would prevent any setTimeout callbacks or UI updates from ever running.Key Takeaways 📌
- The callback queue is a FIFO waiting area for async callbacks (macrotasks)
- Callbacks enter the queue from Web APIs after their async work completes
- The event loop moves ONE callback per cycle to the call stack (when stack is empty)
- Microtasks (Promises) have higher priority — they run before any callback queue item
setTimeout(fn, 0)means at minimum 0ms delay, not immediate execution- Heavy synchronous code blocks the callback queue — the queue waits patiently
- After each macrotask, all microtasks are drained before the next macrotask
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript Callback Queue (Task Queue) - Complete Guide with Diagrams.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, asynchronous, callback, queue
Related JavaScript Master Course Topics