Stop 02 · Node.js FundamentalsTopics · 11/18

Async/Await

Part of the Backend Developer Roadmap

In short

async/await lets you write async code that reads like a normal top-to-bottom recipe. Almost every modern Node backend is written this way, so get very comfortable with it.

Syntactic sugar over Promises that lets asynchronous backend code read top-to-bottom like synchronous code, using `try`/`catch` for error handling.

The mascot waits with a folder at an admission counter while clerks serve students at the next windows.

Think of it like this

College admission day

First the fee counter, then document check, then the ID card desk. You can't skip ahead, so you wait at each one. But the office isn't frozen: clerks keep serving other students while you wait. await pauses your function, not the whole server.

Watch it happen

GET /users/7/orders with await

Client
Handler
Database

GET /users/7/orders

1/6A request comes in for a user's orders.

The big ideas

What you need to know

async returns a promise

An async function always returns a promise, even if you write return 5. Callers await it or use .then.

await pauses one function

Only the current function waits. The event loop keeps running everything else.

try/catch works again

A rejected promise becomes a thrown error at the await line, so normal try/catch handles it.

Express 5 catches for you

In Express 5, an error thrown in an async handler goes straight to your error middleware.

See it in code

Walk through the code

js
1import express from "express";2const app = express();3 4app.get("/users/:id/orders", async (req, res) => {5  const user = await db.findUser(req.params.id);6  if (!user) return res.status(404).json({ error: "User not found" });7 8  const orders = await db.findOrders(user.id);9  res.json({ user, orders });10});11 12// Express 5 sends rejected promises from handlers here automatically13app.use((err, req, res, next) => {14  console.error(err);15  res.status(500).json({ error: "Something went wrong" });16});

1/3Await the user, and stop early with 404 if there isn't one.

db is a stand-in for your database layer. In Express 4 you'd need try/catch or a wrapper to forward async errors. Express 5 does it for you.

Save yourself the pain

Common mistakes

Oops

Forgetting await, so user is a Promise and user.id is undefined.

Do this instead

Await every async call whose result you use. TypeScript and the no-floating-promises lint rule help catch this.

Oops

Using await inside forEach and expecting it to wait.

Do this instead

forEach ignores the promises it gets back. Use for...of to go one by one, or Promise.all with map for parallel.

Your mission

Rewrite with async/await

~20 min

Quick check

What does an async function return if you write return 5 inside it?

Go deeper

  1. 1Rewrite a `.then()` chain (e.g. a DB query then a response) using async/await.
  2. 2Practice wrapping async route handlers in try/catch to avoid unhandled rejections.
  3. 3Learn how to run independent async calls in parallel with `Promise.all` instead of sequential awaits.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge