JavaScript is single-threaded, yet it handles tasks like API calls, timers, and user interactions efficiently β thanks to callbacks and promises. Let's explore how these tools work together and how to manage multiple async operations.
π§ Callback & Asynchronicity
A callback is a function passed into another function to run later β perfect for async tasks like fetching data or waiting for a timeout.
setTimeout(() => {
console.log("This runs later");
}, 1000);
But callbacks can lead to callback hell, making code hard to read and maintain.
π Enter Promises
A Promise represents a value that may be available now, later, or never.
const fetchData = new Promise((resolve, reject) => {
setTimeout(() => resolve("Done!"), 2000);
});
fetchData.then(console.log).catch(console.error);
Using async/await
improves readability even more:
async function getData() {
try {
const result = await fetchData;
console.log(result);
} catch (err) {
console.error(err);
}
}
π Handling Multiple Promises
JavaScript provides powerful utilities for handling multiple promises at once:
β
Promise.all([...])
Waits for all promises to resolve. Fails fast if any reject.
Promise.all([p1, p2, p3])
.then(console.log)
.catch(console.error);
π§ Promise.allSettled([...])
Waits for all to settle (resolve or reject) and returns results for each.
Promise.allSettled([p1, p2, p3]).then(console.log);
π Promise.race([...])
Returns the first settled (resolve or reject) promise.
Promise.race([p1, p2]).then(console.log).catch(console.error);
π₯ Promise.any([...])
Returns the first fulfilled promise. Ignores rejections unless all fail.
Promise.any([p1, p2]).then(console.log).catch(console.error);
π§© Final Thoughts
- Callbacks introduced async flow.
- Promises simplified it.
-
Promise combinators (
all
,allSettled
,race
,any
) give us flexible control over multiple tasks. - Use
async/await
for cleaner, more readable code.
Top comments (0)