Programming Languages

Async/Await in JavaScript Explained Simply (With Examples)

Promises confuse a lot of people. Async/await is the syntax that makes asynchronous JavaScript read like ordinary, top-to-bottom code.

By Justin SchmellaUpdated May 30, 202610 min read
Code editor showing an async function fetching data with await
Async/await turns callback spaghetti into readable, sequential code.

JavaScript does a lot of waiting — for network requests, files, and timers. Async/await is the modern syntax that lets you write code that waits without freezing the page or nesting callbacks five levels deep.

By the end of this tutorial you'll understand what async and await actually do, how to handle errors, and the mistakes that trip up almost everyone at first.

What problem does async/await solve?

Many operations in JavaScript don't finish immediately. Fetching data from a server might take a fraction of a second — an eternity for a computer. JavaScript handles this with Promises: objects that represent a value that will exist later. Async/await is simply nicer syntax for working with those Promises.

The basics: async and await

Marking a function with `async` means it always returns a Promise. Inside that function, `await` pauses execution until a Promise settles, then gives you the result — without blocking the rest of your program.

async function getUser() {
  const response = await fetch('/api/user');
  const user = await response.json();
  return user;
}

Notice how the code reads top to bottom, like synchronous code, even though each await is non-blocking under the hood. That readability is the whole point.

Handling errors with try/catch

Because awaited Promises can reject, you wrap them in a try/catch block. This is far cleaner than chaining `.catch()` on every Promise.

async function getUser() {
  try {
    const res = await fetch('/api/user');
    if (!res.ok) throw new Error('Request failed');
    return await res.json();
  } catch (err) {
    console.error('Could not load user:', err);
    return null;
  }
}

Running tasks in parallel

A classic beginner mistake is awaiting things one after another when they could run at the same time. If two requests don't depend on each other, fire them together with Promise.all to cut your waiting time roughly in half.

const [user, posts] = await Promise.all([
  fetch('/api/user').then(r => r.json()),
  fetch('/api/posts').then(r => r.json()),
]);

Common mistakes to avoid

  • Forgetting that `await` only works inside an `async` function.
  • Awaiting independent operations sequentially instead of with Promise.all.
  • Forgetting to handle rejected Promises, leading to silent failures.
  • Using `await` inside a regular array loop callback like forEach, which won't wait as expected.

Expert insights

  • Async/await doesn't make code faster — it makes it readable. Performance comes from running independent work in parallel, not from the syntax itself.
  • If you ever see an 'unhandled promise rejection' warning, it almost always means an awaited call needs a try/catch around it.

Statistics & data

  • Async/await has been supported in all modern browsers and Node.js since 2017, so it's safe to use everywhere today without transpilation for most projects.

Key takeaways

  • async makes a function return a Promise; await pauses until a Promise resolves.
  • Wrap awaited calls in try/catch to handle errors cleanly.
  • Use Promise.all to run independent tasks in parallel.
  • await only works inside async functions (or top-level in modules).

Frequently asked questions

Is async/await better than Promises?

It's built on Promises, not a replacement. Async/await is usually more readable, but both are valid and you'll often mix them — for example using Promise.all inside an async function.

Why does my await not work?

The most common reason is that await is being used outside an async function. Make sure the enclosing function is marked async, or use top-level await in a module.

Does await block the whole page?

No. It pauses only the current async function while letting the rest of your application keep running, so the UI stays responsive.

External references

Keep learning with StackForge

New, expert-reviewed tutorials are published regularly. Explore more guides in Programming Languages to deepen your skills.

More Programming Languages guides →
Portrait of Justin Schmella, Senior Industry Researcher & Content Specialist

Written & reviewed by

Justin Schmella

Senior Industry Researcher & Content Specialist

Justin Schmella is a senior software engineer and technical educator with more than eight years of hands-on experience shipping production systems across web, cloud, and developer tooling. He began his career as a full-stack developer at a fast-growing SaaS company, where he led the migration of a monolithic application to a modern, service-oriented architecture used by hundreds of thousands of users.

Related tutorials