# async and await

async and await let you write code that waits for promises as if it were a recipe, one step under another, with try and catch for the steps that fail.

Journeyman · JavaScript · Updated November 1, 2026

## After this lesson you can

- Write an async function that awaits each step in order and catches a failure with try and catch
- Explain what an async function returns, and spot a missing await

## Key takeaways

- An async function always returns a promise. Whatever it returns becomes the promise's value, and an error it throws rejects the promise.
- await, read "wait for this", pauses the async function until a promise settles and gives you its value. The rest of the program keeps running.
- Put await inside try and catch to handle a rejected promise, the same way you handle any other error.
- Forget await and you get the promise instead of its value, such as [object Promise] in a message, and try and catch can't see its failure.
- await works inside an async function, and at the top level of a module. Anywhere else it's a SyntaxError.

Open almost any modern JavaScript project, a React app, a Node server, a browser extension, and you'll see the words `async` and `await` everywhere. They're how professionals write code that waits: load the user, then load their orders, then show the page, with a friendly message if anything fails. They work on the same promises you met in *Promises: then, catch and finally*, but they let you write the steps one under another, the way you'd write a recipe, instead of as a chain of `.then` calls.

## An async function always returns a promise

Put the word `async` in front of a function, and the function always returns a promise, whatever its `return` says:

```javascript
async function pizzaOfTheDay() {
  return 'Pepperoni';
}

const result = pizzaOfTheDay();
console.log(result);

result.then((pizza) => console.log(`Today's pizza: ${pizza}`));
```

```text
Promise { 'Pepperoni' }
Today's pizza: Pepperoni
```

The function returned the text `'Pepperoni'`, but the caller got a promise fulfilled with it. In the same way, if an async function throws an error, the caller gets a rejected promise. An arrow function can be async too: `const pizzaOfTheDay = async () => 'Pepperoni';`.

## await: wait for this

Inside an async function, `await` (read it "wait for this") goes in front of a promise. It pauses the function until the promise settles, then hands you the value, so you can store it in a variable like any other value:

```javascript
function placeOrder(pizza) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(`Your ${pizza} is ready`), 1000);
  });
}

async function pickUp() {
  console.log('Waiting for the buzzer...');
  const message = await placeOrder('Hawaiian');
  console.log(message);
}

pickUp();
console.log('Meanwhile, the next customer orders');
```

```text
Waiting for the buzzer...
Meanwhile, the next customer orders
Your Hawaiian is ready
```

`await` pauses **only** `pickUp`, not the whole program. While `pickUp` waits for its pizza, the line after `pickUp();` runs, and in a web page, clicks and typing keep working. When the promise is fulfilled, `pickUp` carries on from the line it stopped at.

**Try it.** Save it as `pickup.js` and run `node pickup.js`. Then add a second `await placeOrder('Veggie')` inside `pickUp` and predict how long the whole run takes before you try it.

## The whole order, top to bottom

Here's the chain from the last lesson, written with `await`. Each step waits for the one before it, and its result lands in a variable with a name:

```javascript
function step(message, ms) {
  return new Promise((resolve) => setTimeout(() => resolve(message), ms));
}

async function makePizza() {
  const dough = await step('Dough stretched', 200);
  console.log(dough);
  const toppings = await step('Sauce and cheese on', 100);
  console.log(toppings);
  const baked = await step('Baked for 90 seconds', 300);
  console.log(baked);
  return 'Boxed and ready';
}

makePizza().then((message) => console.log(message));
```

```text
Dough stretched
Sauce and cheese on
Baked for 90 seconds
Boxed and ready
```

It prints the same lines as the chain, but it reads like the recipe card on the kitchen wall. Both ways are correct, and you'll meet both in other people's code: `await` is how most new code is written, and `.then` is still handy for one quick step.

## try and catch around await

When a promise you `await` is rejected, `await` throws its reason as an error, right on that line. So you handle it with `try` and `catch`, as in *Handling Errors with try, catch and finally*: the code that might fail goes in the `try { }` block, and if anything in it throws, JavaScript jumps to the `catch { }` block, with the error in a variable. A `finally { }` block runs either way.

```javascript
function addTopping(topping) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (topping === 'mushrooms') {
        reject(new Error("Sorry, we're out of mushrooms"));
      } else {
        resolve(`${topping} added`);
      }
    }, 300);
  });
}

async function orderPizza(toppings) {
  try {
    for (const topping of toppings) {
      const message = await addTopping(topping);
      console.log(message);
    }
    console.log('Into the oven!');
  } catch (error) {
    console.log(`Order stopped: ${error.message}`);
  } finally {
    console.log('Ticket cleared');
  }
}

orderPizza(['peppers', 'mushrooms', 'olives']);
```

```text
peppers added
Order stopped: Sorry, we're out of mushrooms
Ticket cleared
```

The peppers went on. The mushrooms' promise was rejected, so `await` threw, and the rest of the `try` was skipped: no olives, no oven. The `catch` told the customer, and the `finally` cleared the ticket.

**Try it.** Change the list to `['peppers', 'olives']`. Which lines print now?

## The mistake of forgetting await

Leave out `await`, and nothing waits: you get the promise itself, the buzzer instead of the pizza.

```javascript
function placeOrder(pizza) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(`Your ${pizza} is ready`), 1000);
  });
}

async function checkOrder() {
  const message = placeOrder('Veggie');
  console.log(`Buzzer says: ${message}`);
}

checkOrder();
```

```text
Buzzer says: [object Promise]
```

`[object Promise]` is how a promise looks when it's turned into text. When you see it on a page or in the console, look for a missing `await`. In the same way, `Promise { <pending> }` in a `console.log` means you logged the promise, not its value.

There's a sneakier result too. Without `await`, a rejected promise isn't thrown inside the `try`, so `catch` never sees it:

```javascript
function addTopping(topping) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (topping === 'mushrooms') {
        reject(new Error("Sorry, we're out of mushrooms"));
      } else {
        resolve(`${topping} added`);
      }
    }, 300);
  });
}

async function orderPizza() {
  try {
    addTopping('mushrooms');
    console.log('Topping ordered');
  } catch (error) {
    console.log(`Order stopped: ${error.message}`);
  }
}

orderPizza();
```

It prints `Topping ordered`, which isn't true, and a moment later Node stops the program with `Error: Sorry, we're out of mushrooms`: an unhandled rejection. The `try` had already finished by the time the promise was rejected. With `await addTopping('mushrooms');`, the `catch` handles it.

One more rule: `await` only works inside an `async` function, and at the top level of a module file (see *Modules: import and export*). Use it inside an ordinary function, and the program won't start: Node reports a `SyntaxError`, `Unexpected reserved word` in a module file, or `await is only valid in async functions and the top level bodies of modules` in a plain script.

## Check yourself

2 questions to try on the lesson page.

## So what

`async` and `await` let you write waiting code the way you think about it: do this, wait for it, then do the next thing, and say sorry when it fails. The next lesson, *Waiting for Several Things at Once*, makes it fast: instead of cooking one pizza after another, the whole table's order goes into the oven together.

## Key terms

- [async Function](https://www.ask-codey.com/glossary/async-function)
- [await](https://www.ask-codey.com/glossary/await)
- [try Block](https://www.ask-codey.com/glossary/try-block-javascript)
- [catch Block](https://www.ask-codey.com/glossary/catch-block-javascript)

## Cheat sheets

- [async and await](https://www.ask-codey.com/cheat-sheets/javascript-promises-async-and-await-cheat-sheet)

## Related

- [Promises: then, catch and finally](https://www.ask-codey.com/lessons/javascript-promises-what-is-a-promise)
- [Handling Errors with try, catch and finally](https://www.ask-codey.com/lessons/javascript-errors-try-catch-finally)
- [Waiting for Several Things at Once](https://www.ask-codey.com/lessons/javascript-promises-several-at-once)

Source: https://www.ask-codey.com/lessons/javascript-promises-async-and-await
