Intermediate · Asynchronous JavaScript · topic 38 of 61 · 30 min
async and await
Explanation
Why async/await?
Promise chains are better than callbacks, but long chains with branches and loops are still awkward. async/await (ES2017) is syntax on top of promises that lets you write the same logic top to bottom, with normal if, for and try/catch.
async function checkout(userId) {
try {
const user = await getUser(userId);
const cart = await getCart(user.id);
if (cart.items.length === 0) return 'Cart is empty';
const payment = await charge(user, cart.total);
return `Paid ₹${payment.amount}`;
} catch (err) {
return `Checkout failed: ${err.message}`;
}
}Rules of async and await
- An async function ALWAYS returns a promise. return 5 inside it gives a promise fulfilled with 5; throwing gives a rejected promise.
- await can be used inside async functions (and at the top level of ES modules).
- await promise pauses only this function until the promise settles, then gives its value, or throws its error.
- While the function is paused, the rest of the program keeps running.
async function getFive() { return 5; }
console.log(getFive()); // Promise { 5 } (not 5!)
getFive().then((n) => console.log(n)); // 5Sequential versus parallel
Each await waits before starting the next line. If two calls do not depend on each other, start them both first and then wait for both with Promise.all. This can make a page load twice as fast.
// Slow: about 300 + 300 = 600 ms
const profile = await getProfile(id);
const orders = await getOrders(id);
// Fast: about 300 ms, both run at the same time
const [profile2, orders2] = await Promise.all([getProfile(id), getOrders(id)]);Common mistakes
- Forgetting await: const user = getUser(id); gives a Promise, so user.name is undefined.
- Using await inside forEach: items.forEach(async (i) => await save(i)) does NOT wait; forEach ignores the returned promises. Use for…of for one-by-one, or Promise.all(items.map(save)) for all at once.
- Awaiting in a loop when the calls are independent: slow. Use Promise.all.
- Not catching errors: an await that rejects throws inside the function; without try/catch, the async function's promise rejects and someone must handle it.
// waits for each save in order
for (const item of items) {
await save(item);
}
// or start all and wait once
await Promise.all(items.map((item) => save(item)));Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
async and await · 1/6
In this lesson you will write async code that reads like normal code, with async and await.
Prefer a video by a teacher? Find free videos on “javascript async await explained try catch promise.all” on YouTube ↗
In real life: Loading a dashboard faster
A bank app's home screen needs the account balance, recent transactions and offers. They do not depend on each other, so the app starts all three requests together with Promise.all. The screen appears in the time of the slowest request instead of the sum of all three.
const fake = (value, ms) => new Promise((r) => setTimeout(() => r(value), ms));
async function loadHome() {
const start = Date.now();
const [balance, txns, offers] = await Promise.all([fake(52000, 30), fake(['UPI ₹250'], 30), fake([], 30)]);
return { balance, txns: txns.length, offers: offers.length, ms: Date.now() - start };
}
loadHome().then(console.log); // about 30 ms, not 90Practice (0/3 done)
Rewrite getName as an async function that awaits fetchUser(id) and returns the user's name.
Write safeBalance(getBalance) that awaits getBalance() and returns its number, or returns 0 if it rejects. Use try/catch.
saveAll(items, save) must save every item and return how many were saved, running all saves AT THE SAME TIME. The test checks that saves overlap. (Hint: forEach with async does not wait.)
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Promise.all, allSettled, race and anyAsynchronous JavaScript · same module
- async/await and error handlingFrontend Web Development · Async JavaScript, modules and tools
- Futures and async/awaitFlutter and Dart · Async Dart and packages
- async and await: waiting without blockingC# and .NET · Exceptions, delegates, events and async
- Async Rust with tokioRust Programming · Concurrency and async
- Node.js: JavaScript on the serverBackend Development · Node.js and Express
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
async function f() { return 3; } What is f()?
Answer: A promise that fulfils with 3
async functions always return promises.
What does await do?
Answer: Pauses the current async function until the promise settles
Other code keeps running while this function is paused.
Two independent requests each take 1 s. With await one after the other, the total is about…
Answer: 2 s
Sequential awaits add up; Promise.all would take about 1 s.
How do you handle a rejected await?
Answer: try/catch around the await
A rejection is thrown at the await, so catch it.
Three independent requests each take about 1 second. How long does await Promise.all([a(), b(), c()]) take?Related
Answer: About 1 second
Promise.all starts them together, so the total is about the slowest one. Awaiting them one by one would take about 3 seconds.
Does await block the whole Dart program?Related
Answer: No, it pauses only the current function while the event loop keeps working
Other events continue.
What kind of work benefits most from async/await?Related
Answer: Waiting for network, disk or database (I/O)
async frees threads during I/O waits.
What is the danger of a long CPU loop inside an async task?Related
Answer: It blocks the worker thread, so other tasks stall
Tasks must yield at .await points; use spawn_blocking for heavy work.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 3 more topics in “Asynchronous JavaScript” before its exam: Promise.all, allSettled, race and any, The event loop, fetch: talking to servers.
- Module 8 exam: Asynchronous JavaScript · 12 questions · 25 min, without help. 6 topics of this module still to finish first.
- Then the next module, TypeScript basics. 61 topics left in the course before the final exam.