From callbacks to Promises to Async/Await. Learn how to write clean, non-blocking code with interactive examples and visual explanations.
const myPromise = new Promise((resolve, reject) => {
const success = true;
setTimeout(() => {
if (success) {
resolve("Operation successful! 🎉");
} else {
reject("Operation failed! ❌");
}
}, 2000);
});
// Consuming the Promise
myPromise
.then(result => {
console.log("Success:", result);
})
.catch(error => {
console.log("Error:", error);
})
.finally(() => {
console.log("Cleanup complete");
});
Avoid "Callback Hell" by chaining promises. Each .then() returns a
new promise, allowing sequential asynchronous operations.
fetchUserData(123)
Returns Promise<User>
.then(user => ...)
Returns Promise<Posts>
.then(posts => ...)
Returns postCount
function fetchUserData(userId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: userId, name: "John Doe" });
}, 1000);
});
}
function fetchUserPosts(user) {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{ title: "Post 1", content: "Hello" },
{ title: "Post 2", content: "World" }
]);
}, 1000);
});
}
// Chaining
fetchUserData(123)
.then(user => {
console.log("User:", user);
return fetchUserPosts(user);
})
.then(posts => {
console.log("Posts:", posts);
return posts.length;
})
.then(count => {
console.log("Total:", count);
})
.catch(error => {
console.error("Error:", error);
});
Write asynchronous code that looks and behaves like synchronous code. Easier to read, easier to debug.
Automatically wraps the return value in a Promise. Makes any function return a Promise.
Pauses execution until the Promise resolves. Can only be used inside async functions.
Use standard try/catch blocks instead of .catch(). Much more intuitive!
function getData() {
return fetchUserData(123)
.then(user => {
console.log(user);
return fetchUserPosts(user);
})
.then(posts => {
console.log(posts);
return processPosts(posts);
})
.then(result => {
console.log(result);
})
.catch(error => {
console.error(error);
});
}
Key Insight: Both examples do exactly the same thing! Async/await is just cleaner syntax for the same Promise-based behavior.
Utility methods for handling multiple promises concurrently. Essential for performance optimization.
Wait for all or fail fast
Waits for all promises to resolve. If any promise rejects, immediately rejects with that error.
First to settle wins
Returns the first promise that settles (resolves or rejects). Great for timeouts!
Wait for all regardless
Waits for all promises to settle, regardless of outcome. Never rejects, always resolves with status array.
Run live JavaScript demos to see Promises in action
| Aspect | Promises (.then/.catch) | Async/Await |
|---|---|---|
| Syntax Style | Functional, chain-based | Procedural, synchronous-like |
| Error Handling | .catch() |
try/catch blocks |
| Readability | Can become nested (callback hell) | Flat, linear structure |
| Debugging | Harder to step through | Standard debugging (breakpoints) |
| Browser Support | ES6 (2015)+ | ES2017+ (Modern browsers) |
Use .catch() or try/catch for every async operation to prevent unhandled promise rejections.
Use async/await for cleaner code, but understand Promises underneath.
Use Promise.all() for independent operations instead of awaiting sequentially.
Avoid mixing .then() with async/await in the same function for consistency.