Skip to content

Intermediate · Asynchronous JavaScript · topic 38 of 61 · 30 min

async and await

Explanation

async functions let you write promise code that reads like normal step-by-step code. Inside one, await pauses that function (not the whole program) until a promise settles, and gives you its value or throws its error, which you handle with try/catch. Use Promise.all when independent steps can run at the same time.

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.

javascript
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.
javascript
async function getFive() { return 5; }
console.log(getFive());               // Promise { 5 } (not 5!)
getFive().then((n) => console.log(n)); // 5

Sequential 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.

javascript
// 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

  1. Forgetting await: const user = getUser(id); gives a Promise, so user.name is undefined.
  2. 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.
  3. Awaiting in a loop when the calls are independent: slow. Use Promise.all.
  4. 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.
javascript
// 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)));
Careful: Never make the main thread wait with a busy loop "until the data arrives". There is no way to make async code synchronous. Make the caller async too, or use then. Async spreads upward: if a function needs an awaited value, it becomes async, and so does its caller.
Think of it like this: await is like a chef who puts dal on the stove and says "call me when it boils". He does not stare at the pot; the kitchen keeps working on other orders. When it boils, he continues his recipe from exactly where he left it.
Tip: Top-level await works in ES modules (and in the browser console), so a module can write const config = await loadConfig(); at the top.

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

async / await

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.

javascript
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 90

Practice (0/3 done)

Task 1 · Code · Javascript

Rewrite getName as an async function that awaits fetchUser(id) and returns the user's name.

Task 2 · Code · Javascript

Write safeBalance(getBalance) that awaits getBalance() and returns its number, or returns 0 if it rejects. Use try/catch.

Task 3 · Code · Javascript

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

Question 1

1.async function f() { return 3; } What is f()?

Question 2

2.What does await do?

Question 3

3.Two independent requests each take 1 s. With await one after the other, the total is about…

Question 4

4.How do you handle a rejected await?

Read more (free)

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.

From async/await and error handling

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.

From Futures and async/await

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.

From async and await: waiting without blocking

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.

From Async Rust with tokio

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

  1. 3 more topics in “Asynchronous JavaScript” before its exam: Promise.all, allSettled, race and any, The event loop, fetch: talking to servers.
  2. Module 8 exam: Asynchronous JavaScript · 12 questions · 25 min, without help. 6 topics of this module still to finish first.
  3. Then the next module, TypeScript basics. 61 topics left in the course before the final exam.

← Previous: Promises