Promises and async/await
Async control flow with async functions, await, try/catch, serial loops, and parallel mapping.
A Promise represents a value that will be available in the future. async and await are syntax over promises. Every async function returns a Promise, and await unwraps one.
async and await let asynchronous code read like step-by-step code. Wrap await calls in try/catch to handle rejections.
async function fetchUser(id) {
const res = await fetch(`https://api.example.com/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
async function main() {
try {
const user = await fetchUser(1);
console.log(user.name);
} catch (err) {
console.error("Failed:", err.message);
}
}
main();await inside a for-of loop runs iterations serially, so each waits for the previous one. Promise.all with .map starts them in parallel. Know which one you want.
const ids = [1, 2, 3, 4, 5];
// Serial: each request waits for the previous one.
async function serial() {
for (const id of ids) {
const user = await fetchUser(id);
console.log(user.name);
}
}
// Parallel: all requests are in flight at once.
async function parallel() {
const users = await Promise.all(ids.map((id) => fetchUser(id)));
users.forEach((u) => console.log(u.name));
}
async function broken() {
ids.forEach(async (id) => {
const user = await fetchUser(id); // forEach does not wait
console.log(user.name);
});
console.log("done?"); // runs before users are fetched
}In production
Do not use forEach when you need to wait for async work. Use for...of for serial work or Promise.all(ids.map(...)) for parallel work.
Enjoyed this? Get more software craft delivered to your inbox.