JavaScript Lesson 17: Promises and Async/Await
JavaScript is single-threaded but can handle async operations (like fetching data) without blocking. Promises and async/await are the modern way to work with asynchronous code.
The Problem: Callbacks
// OLD WAY — callback hell
getUser(1, function(user) {
getOrders(user.id, function(orders) {
getProducts(orders[0].id, function(product) {
// deeply nested!
});
});
});
Promises — The Solution
// A Promise is a container for a future value
// States: pending → fulfilled (resolved) OR rejected
const promise = new Promise((resolve, reject) => {
// simulate async work
setTimeout(() => {
const success = true;
if (success) {
resolve("Data loaded!");
} else {
reject("Something went wrong");
}
}, 1000);
});
promise
.then(result => console.log(result)) // "Data loaded!"
.catch(error => console.error(error)) // if rejected
.finally(() => console.log("Done")); // always runs
async/await — Write Async Like Sync
// async keyword makes a function return a Promise
async function fetchUser(id) {
try {
// await pauses until the Promise resolves
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const user = await response.json();
return user;
} catch (error) {
console.error("Failed to fetch:", error);
throw error;
}
}
// Call it
fetchUser(1).then(user => console.log(user));
Promise.all — Run Multiple in Parallel
// Fetch multiple things at the same time
async function fetchAllData() {
try {
// All three requests run IN PARALLEL (faster!)
const [users, posts, comments] = await Promise.all([
fetch("https://api.example.com/users").then(r => r.json()),
fetch("https://api.example.com/posts").then(r => r.json()),
fetch("https://api.example.com/comments").then(r => r.json())
]);
console.log(users.length, posts.length);
} catch (error) {
console.error("One request failed:", error);
}
}
🏋️ Practice Task
Create a function that simulates a delay using a Promise (hint: use setTimeout inside a Promise). Write: const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)). Then write an async function that waits 1 second, logs “1 second passed”, waits another second, logs “done”.
💡 Hint: async function run() { await delay(1000); console.log(“1 second”); await delay(1000); console.log(“done”); }