Async JavaScript
Event Loop
JavaScript is single-threaded but handles async operations using the event loop.
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Call Stack │ ←── │ Event Loop │ ←── │ Task Queue │
└─────────────┘ └──────────────┘ └─────────────┘
┌──────────────────┐
│ Microtask Queue │
└──────────────────┘
Execution Order
- Execute synchronous code on the call stack.
- Process all microtasks (Promises,
queueMicrotask). - Process one macrotask (
setTimeout,setInterval, I/O). - Repeat.
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
// Output: 1, 4, 3, 2
// Sync first → microtask (Promise) → macrotask (setTimeout)
Callbacks
function fetchData(callback) {
setTimeout(() => {
callback("data");
}, 1000);
}
// Callback hell
fetchData((data) => {
processData(data, (result) => {
saveData(result, (response) => {
// deeply nested — hard to read
});
});
});
Promises
A Promise represents a value that may be available now, later, or never.
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("done!"), 1000);
});
promise
.then((value) => console.log(value))
.catch((err) => console.error(err))
.finally(() => console.log("cleanup"));
Promise Static Methods
// All must resolve
Promise.all([p1, p2, p3]).then((results) => {});
// First to settle
Promise.race([p1, p2, p3]).then((fastest) => {});
// All settle (no rejection)
Promise.allSettled([p1, p2]).then((results) => {});
// First to resolve (ignores rejections)
Promise.any([p1, p2]).then((first) => {});
Async / Await
Syntactic sugar over Promises — makes async code look synchronous.
async function getData() {
try {
const response = await fetch("/api/data");
const data = await response.json();
return data;
} catch (error) {
console.error("Failed:", error);
}
}
Parallel Execution
// Sequential — slow
const a = await fetchA();
const b = await fetchB();
// Parallel — fast
const [a, b] = await Promise.all([fetchA(), fetchB()]);
Key Takeaways
- JavaScript uses an event loop to handle async operations on a single thread.
- Microtasks (Promises) run before macrotasks (setTimeout).
- Promises solve callback hell; async/await makes Promises readable.
- Use
Promise.all()for parallel execution.