Home / Topic Library / JavaScript / Async & Promises
⚡ JavaScript Topic Library

JavaScript Async — Promises & async/await Made Clear

JavaScript runs on one thread — it can't stop and wait, or the whole page freezes. Async code is how it starts slow work (network, timers) and reacts when results arrive.

⚡ Quick Answer

A Promise is a placeholder for a future value. Modern code consumes them with async/await: inside an async function, await promise pauses that function (not the page!) until the value arrives. Wrap awaits in try/catch for errors.

§Why async exists

why.js
console.log("1: start");

setTimeout(() => {
  console.log("3: after 2s (page never froze)");
}, 2000);

console.log("2: this runs IMMEDIATELY");
// JS never blocks — it schedules and moves on

§Promises — the placeholder

promises.js
const delay = (ms) =>
  new Promise(resolve => setTimeout(resolve, ms));

delay(1000)
  .then(() => console.log("1 second later"))
  .then(() => delay(1000))
  .then(() => console.log("2 seconds — chained!"))
  .catch(err => console.error("something failed:", err));

§async/await — promises made readable

async_await.js
async function loadUser(id) {
  const res = await fetch(`/api/users/${id}`);   // pause HERE
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const user = await res.json();
  return user;                    // async fns always return a promise
}

// consuming it:
const user = await loadUser(1);    // top-level await (modules)
console.log(user.name);

§Error handling

errors.js
async function safeLoad() {
  try {
    const data = await loadUser(1);
    render(data);
  } catch (err) {
    console.error("load failed:", err.message);
    showRetryButton();
  } finally {
    hideSpinner();               // runs either way
  }
}

§Parallel work with Promise.all

parallel.js
// sequential — slow (one after another):
const a = await fetchA();
const b = await fetchB();

// parallel — fast (both at once):
const [resA, resB] = await Promise.all([fetchA(), fetchB()]);

// don't want one failure to kill both?
const results = await Promise.allSettled([fetchA(), fetchB()]);
// [{status:"fulfilled", value}, {status:"rejected", reason}]

§Common Mistakes to Avoid

🚨 Watch out for these
  • Forgetting await — calling an async function without await gives you a Promise object, not the value — console.log(loadUser()) prints Promise {<pending>}
  • await in a non-async function — SyntaxError — the containing function needs the async keyword (or use a module for top-level await)
  • Sequential awaits for independent work — two independent fetches awaited one-by-one take double time — Promise.all them

§Frequently Asked Questions

What is a Promise in simple terms?

An IOU for a value that isn't ready yet — it's pending, then either fulfills with a value or rejects with an error, and you attach code to run in each case.

Does await freeze the page?

No — it pauses only that async function. The browser keeps handling clicks and rendering while the awaited work completes.

async/await vs .then — which should I use?

They're the same machinery; async/await reads like normal code and plays better with try/catch and loops, so it's the modern default.

What's the difference between Promise.all and allSettled?

all rejects immediately if ANY promise fails; allSettled always waits for every promise and reports each outcome.

🎓 Want to master JavaScript properly?This reference covers one topic — the full free course takes you from zero to real projects, with quizzes and a certificate.
Start the Free JavaScript Course →

§Related JavaScript Topics

← EventsFetch API →