New here? See how enrollment works →
JavaScript · · 1 min read

async and await in JavaScript, explained with fetch

When your code asks a server for data, the answer takes time. JavaScript does not wait. It keeps running the next lines and comes back when the data arrives. async and await let you write that code in the order you think about it.

The basic pattern

async function loadUser(id) {
  const res = await fetch(`/api/users/${id}`);
  const user = await res.json();
  return user;
}

The async keyword marks the function. Inside it, await pauses that function until the promise settles. The rest of your page keeps working.

fetch does not fail on 404

fetch only rejects when the network fails. A 404 or 500 response still resolves. Check res.ok yourself:

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

Catch errors with try and catch

try {
  showLoading();
  const user = await loadUser(42);
  render(user);
} catch (err) {
  showError(err.message);
} finally {
  hideLoading();
}

The finally block runs in both cases, so you hide the spinner once.

Run requests in parallel

Two awaits in a row run one after the other. If the requests do not depend on each other, start both and wait for both:

const [user, orders] = await Promise.all([
  loadUser(42),
  loadOrders(42)
]);

This cuts the waiting time to the slower of the two requests.

Three states to handle

Each request your interface makes needs a loading state, an error state and an empty state. Beginners often build only the happy path. Open the Network panel in Chrome DevTools, set throttling to the 3G preset, and then to Offline. You will find the missing states in a minute.

Courses on this topic

More from the blog