Async / Await

📚 Lesson 20 of 22  •  ⏱ 12 min read  •  Intermediate

Basic Syntax

JavaScript
// async function always returns a Promise
async function getData() {
  // await pauses execution until the Promise resolves
  const response = await fetch("https://api.example.com/data");
  const data     = await response.json();
  return data;
}

// Arrow function syntax
const getData = async () => {
  const res = await fetch("/api/posts");
  return res.json();
};

Error Handling with try/catch

JavaScript
async function loadUser(id) {
  try {
    const res  = await fetch(`/api/users/${id}`);

    if (!res.ok) {
      throw new Error(`HTTP error: ${res.status}`);
    }

    const user = await res.json();
    return user;

  } catch (error) {
    console.error("Failed to load user:", error.message);
    return null;  // or re-throw

  } finally {
    // Runs always — hide loading spinner here
  }
}

Parallel Requests — Don't Await in Sequence

JavaScript
// SLOW — sequential (each waits for the previous)
const user  = await fetchUser();
const posts = await fetchPosts();  // waits until user is done

// FAST — parallel (both start at the same time)
const [user, posts] = await Promise.all([
  fetchUser(),
  fetchPosts()
]);
// Finishes in max(userTime, postsTime) instead of userTime+postsTime

Real Example — Load & Render Data

JavaScript
async function loadCourses() {
  const list = document.querySelector("#courses-list");
  list.innerHTML = '<p>Loading...</p>';

  try {
    const res     = await fetch("/api/courses");
    const courses  = await res.json();

    list.innerHTML = courses
      .map(c => `<div class="card"><h3>${c.title}</h3></div>`)
      .join("");

  } catch (e) {
    list.innerHTML = '<p>Failed to load. Please try again.</p>';
  }
}

document.addEventListener("DOMContentLoaded", loadCourses);

Top-Level Await (ES2022)

JavaScript
// In ES modules (.mjs or type="module") you can await at top level
const config = await fetch("/config.json").then(r => r.json());
console.log(config.apiUrl);

// Not available in regular scripts — wrap in async IIFE instead
(async () => {
  const data = await fetch("/data").then(r => r.json());
})();