CodingNic

Modern JavaScript for Node.js

Async/Await

Modern JavaScript for Node.js 12 min read

Async/Await

Objectives

By the end of this lesson, you should be able to:

  • Write an async function and await a promise inside it
  • Handle a rejected promise with try/catch around await
  • Explain when sequential await calls should become parallel ones

💡 Why this matters: Async/await is the standard way modern Node.js and Express code handles asynchronous work, database queries, file reads, external API calls. Every route handler from Module 5 onward that touches anything asynchronous uses this pattern.

⚠️ A note on verification: every snippet and output in this lesson was actually run with Node.js.

async and await

javascript
function fetchUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id <= 0) reject(new Error("invalid id"));
      else resolve({ id, name: "Erin Castillo" });
    }, 10);
  });
}

async function loadUser(id) {
  const user = await fetchUser(id);
  console.log("loaded:", user.name);
  return user;
}

loadUser(1);
text
loaded: Erin Castillo

async before a function declaration means it always returns a promise, and unlocks the ability to use await inside it. await fetchUser(id) pauses execution of loadUser until that promise settles, then continues with the resolved value, user, no .then() callback needed. The code reads top to bottom, like synchronous code, even though fetchUser is genuinely asynchronous underneath.

Error Handling with try/catch

javascript
async function loadUser(id) {
  try {
    const user = await fetchUser(id);
    console.log("loaded:", user.name);
  } catch (err) {
    console.log("failed:", err.message);
  }
}

loadUser(-1);
text
failed: invalid id

A rejected promise, when awaited, throws, exactly like throw from Lesson 5. This means ordinary try/catch handles it directly, await fetchUser(-1) throws the rejection’s error, which catch (err) receives, no separate .catch() method needed, this is the same error-handling syntax already familiar from synchronous code.

Sequential vs Parallel await

javascript
async function sequential() {
  console.time("sequential");
  const a = await fetchUser(1);
  const b = await fetchUser(2);
  console.timeEnd("sequential");
  console.log(a.name, b.name);
}

async function parallel() {
  console.time("parallel");
  const [a, b] = await Promise.all([fetchUser(1), fetchUser(2)]);
  console.timeEnd("parallel");
  console.log(a.name, b.name);
}
text
sequential: 20.773ms
User 1 User 2
parallel: 10.447ms
User 1 User 2

sequential() awaits fetchUser(1), then only after that finishes, starts fetchUser(2), roughly doubling the total wait. parallel() starts both calls together with Promise.all() (previous lesson), then awaits them as a group, both fetches happen at the same time, the whole operation takes roughly as long as the slower one alone, not the sum of both. When two async operations don’t depend on each other’s results, running them with Promise.all() instead of separate sequential awaits is a real, measurable improvement, not just a style preference.

Try It

  1. Write an async function getProduct(id) that awaits a promise-returning fetchProduct function and logs the result.
  2. Add a try/catch around the await in question 1, handling a rejection if id is invalid.
  3. Write two independent async operations and run them with sequential await calls, then rewrite them using Promise.all(), comparing the two.
  4. Explain, in your own words, why await Promise.all([a, b]) is generally faster than await a; await b; when a and b don’t depend on each other.

Recap

  • async functions always return a promise, await pauses until a promise settles, letting async code read like synchronous code.
  • A rejected, awaited promise throws, handled with ordinary try/catch, no separate .catch() needed.
  • Independent async operations should run with Promise.all() rather than sequential await calls, real time savings, not just style.

Next lesson: this module’s exercises, combining every modern JavaScript feature covered so far.