How does async/await work in JavaScript?

HTML, CSS & JS 2 min read
Short answer

async marks a function as returning a promise. await pauses inside that function until a promise settles, so asynchronous steps read like sequential ones.

javascript
async function loadLessons() {
  const response = await fetch('/api/lessons');
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  const data = await response.json();
  return data;
}

The same thing with raw promises:

javascript
function loadLessons() {
  return fetch('/api/lessons')
    .then((response) => {
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      return response.json();
    });
}

Identical behaviour. The async version stays readable when there are five steps and a conditional in the middle.

#Errors use try/catch

javascript
try {
  const data = await loadLessons();
} catch (error) {
  console.error('Could not load:', error);
}

#Do not await in sequence when you can parallelise

javascript
// Slow — 600ms if each takes 200ms
const a = await fetchA();
const b = await fetchB();
const c = await fetchC();

// Fast — 200ms, all three at once
const [a, b, c] = await Promise.all([fetchA(), fetchB(), fetchC()]);

Sequential await is correct only when a later call depends on an earlier result.

Promise.allSettled is the variant that does not reject when one fails — use it when partial results are still useful.

#await only works inside async

At the top level of a module you can use it directly. In a classic script you cannot; wrap it:

javascript
(async () => {
  const data = await loadLessons();
})();

#async functions always return a promise

javascript
async function get() { return 1; }
get();          // Promise { 1 }, not 1
await get();    // 1