mosaddik.dev
All posts

JavaScript async and await explained, with real examples

Mosaddik Billah 3 min read

JavaScript & React

Lines of code on a dark screen
Photo by Florian Olivo on Unsplash
On this page
  1. Promises: the result that arrives later
  2. await: wait for the result
  3. Handling errors
  4. Running things in parallel
  5. Common mistakes
  6. Where you’ll use this

Almost everything useful in web code takes time: loading data, calling an API, saving a form. JavaScript doesn’t stop and wait for these. It starts the work, carries on, and deals with the result when it arrives. async and await are how you write that kind of code so it still reads top to bottom.

Promises: the result that arrives later#

Think of ordering at a café. You pay, get a receipt, and step aside. The receipt isn’t the coffee, but it promises a coffee, or an apology if they’ve run out.

A promise is that receipt. Functions like fetch return one straight away, and it later either resolves with a value or rejects with an error:

JavaScript
const promise = fetch("https://api.example.com/products");
console.log(promise); // Promise { <pending> }

await: wait for the result#

Inside a function marked async, await pauses that function until the promise settles, then gives you the value:

JavaScript
async function loadProducts() {
  const response = await fetch("https://api.example.com/products");
  const products = await response.json();
  return products;
}

Only loadProducts pauses. The rest of the page keeps working. And because the function is async, it returns a promise too, so its caller uses await as well:

JavaScript
const products = await loadProducts();

Handling errors#

If an awaited promise rejects, await throws. Catch it with try…catch, like any other error:

JavaScript
async function loadProducts() {
  try {
    const response = await fetch("https://api.example.com/products");
    if (!response.ok) {
      throw new Error(`Request failed: ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("Could not load products", error);
    return [];
  }
}

Note the response.ok check: fetch only rejects when the request can’t be made at all. A 404 or 500 response still resolves, so you have to check the status yourself.

Running things in parallel#

Each await waits for the previous line to finish. That’s right when one step needs the result of another, but slow when the requests are independent:

JavaScript
// Slow: about 3 seconds if each request takes 1 second
const user = await getUser();
const orders = await getOrders();
const messages = await getMessages();

Start them all at once and wait for all of them with Promise.all:

JavaScript
// Faster: about 1 second
const [user, orders, messages] = await Promise.all([
  getUser(),
  getOrders(),
  getMessages(),
]);

Promise.all rejects as soon as any one of them fails. If you want every result, including failures, use Promise.allSettled and check each result’s status.

Common mistakes#

Forgetting await. You get a promise instead of the value:

JavaScript
const products = loadProducts(); // a Promise, not an array
products.map(...);               // TypeError: products.map is not a function

Using await inside forEach. forEach doesn’t wait for async callbacks, so code after the loop runs before the work is done:

JavaScript
// Wrong: "Done" logs before any item is saved
items.forEach(async (item) => {
  await save(item);
});
console.log("Done");

// Right, one at a time:
for (const item of items) {
  await save(item);
}

// Right, all at once:
await Promise.all(items.map((item) => save(item)));

Not handling errors. A rejected promise nobody catches shows up as an “Uncaught (in promise)” error, and the user sees nothing happen. Decide where each error should be handled, and show a message when something fails.

Where you’ll use this#

The same patterns appear everywhere: fetch in the browser, database queries in Node.js, and Wix Velo, where wixData.query(...).find() returns a promise. For a Velo example, see how to call an external API from Wix with Velo.

If you need custom code or API integrations for your site, I do custom API integration and Wix Velo development.

Comments