AiTechWorlds
AiTechWorlds
Call stack, microtask queue, macrotask queue, Node.js phases, and practical patterns for non-blocking JavaScript.
JavaScript is single-threaded β only one piece of code runs at a time. But it handles I/O, timers, and network requests without blocking using an event loop that coordinates between the call stack, Web APIs, and task queues.
| Component | Role |
|---|---|
| Call Stack | Tracks function execution (LIFO) |
| Heap | Memory allocation for objects |
| Web APIs | Browser/Node APIs: setTimeout, fetch, DOM events |
| Macrotask Queue | Callbacks from setTimeout, setInterval, I/O |
| Microtask Queue | Callbacks from Promises (.then), queueMicrotask, MutationObserver |
| Event Loop | Moves tasks from queues to call stack when stack is empty |
1. Run all synchronous code (empty the call stack)
2. Process ALL microtasks (Promise callbacks, queueMicrotask)
β Keep processing until microtask queue is empty
3. Render (browser) β if needed
4. Process ONE macrotask (setTimeout/setInterval callback)
5. Process ALL microtasks again
6. Repeat from step 3Key rule: Microtasks always run before the next macrotask.
console.log("1 - sync");
setTimeout(() => console.log("2 - macrotask"), 0);
Promise.resolve()
.then(() => console.log("3 - microtask 1"))
.then(() => console.log("4 - microtask 2"));
console.log("5 - sync");
// Output:
// 1 - sync
// 5 - sync
// 3 - microtask 1
// 4 - microtask 2
// 2 - macrotask| Type | Examples | When Runs |
|---|---|---|
| Microtask | Promise.then/catch/finally, queueMicrotask, MutationObserver | After current task, before next macrotask |
| Macrotask | setTimeout, setInterval, setImmediate (Node), I/O callbacks | One per event loop iteration |
setTimeout(() => console.log("timer"), 0);
// Minimum delay is 4ms in browsers (HTML spec)
// In Node.js, minimum is ~1ms
// Still runs AFTER all microtasks from current taskNode.js has a more structured event loop with phases:
setImmediate vs setTimeout(fn, 0) in Node:
setImmediate(() => console.log("setImmediate"));
setTimeout(() => console.log("setTimeout"), 0);
// Order is non-deterministic outside I/O
// Inside I/O callbacks: setImmediate always runs firstprocess.nextTick β runs before even microtasks:
Promise.resolve().then(() => console.log("promise"));
process.nextTick(() => console.log("nextTick"));
// nextTick
// promise// BAD β blocks for 2 seconds, no I/O can be processed
function blockingWork() {
const end = Date.now() + 2000;
while (Date.now() < end) {} // busy-wait blocks everything
}
// GOOD β break work into chunks
function nonBlockingWork(items, index = 0) {
if (index >= items.length) return;
process(items[index]);
setImmediate(() => nonBlockingWork(items, index + 1));
}
// BETTER β use Worker threads for CPU-heavy work
const { Worker } = require('worker_threads');
const worker = new Worker('./heavy-computation.js');
worker.on('message', (result) => console.log(result));async function example() {
console.log("A");
await Promise.resolve(); // schedules continuation as microtask
console.log("B"); // runs after current sync completes
}
console.log("1");
example();
console.log("2");
// 1
// A
// 2
// B// Allow other callbacks to run between large batches
async function processBatch(items) {
for (let i = 0; i < items.length; i++) {
await processItem(items[i]);
if (i % 100 === 0) {
await new Promise(resolve => setTimeout(resolve, 0)); // yield
}
}
}// Debounce β run after N ms of inactivity
function debounce(fn, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
// Throttle β run at most once per N ms
function throttle(fn, limit) {
let inThrottle = false;
return (...args) => {
if (!inThrottle) {
fn(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}setTimeout(fn, 0) runs immediately β it's always deferred after all pending microtasksPromise.resolve().then(() => Promise.resolve().then(...))) β starves macrotasksawait β it only pauses the current async function, not the event loopsetInterval without clearing it β memory leak; always store the ID and call clearInterval when doneAdvertisement
Get more notes like this daily on Telegram!
Free study notes, cheat sheets & AI tips
Last reviewed on June 13, 2026 by the AiTechWorlds Notes Team. Free cheat sheet β no signup required.
Advertisement
Join AiTechWorlds on Telegram and get daily AI tips, prompt engineering templates, coding resources, and exclusive content β 100% free!
No spam. Leave anytime.