Browser · deeper

First there were callbacks. Then there was the pyramid.

A callback is just "here's a function, call it when you're done". It works. The trouble starts when step two needs step one's answer, and step three needs step two's.

Add steps and watch the code lean right. Real code from 2012 looked like this, and it was called callback hell without irony.

callback style
Fix one

A promise is a box for a value that isn't here yet.

Instead of taking your callback, a slow function hands you a box. You attach what should happen when the box fills (.then) or fails (.catch). Boxes chain flat, not nested.

This box is empty. You are the network. Decide how the request ends.

one promise, three handlers
pending
.then(data => show(data))
.catch(err => toast(err))
.finally(() => hideSpinner())

A promise settles exactly once. After that, it never changes.

Fix two

async/await is the same promise in nicer clothes.

Nothing new happens underneath. await means "pause this function until the box fills, then hand me what's inside". It reads top to bottom, like code that doesn't wait, which is the whole appeal.

Flip between the two spellings. Same behaviour, same promise, same event loop.

same program, two spellings
async function loadUser(id) {
  const res  = await fetch(`/api/users/${id}`);
  const user = await res.json();
  const posts = await fetch(`/api/posts?u=${user.id}`);
  return { user, posts: await posts.json() };
}

An async function always returns a promise, even if you never write the word.

Place your bet

While a function is awaiting, is the page frozen?

No. await doesn't block the thread. It parks this one function and gives the thread back. Clicks, animations, other functions all run. When the box fills, the parked function goes into the queue and resumes when the stack is free.

That's the trick of the whole ecosystem: "waiting" in JavaScript never means "the CPU is waiting". It means "someone else is holding my place in line".

bet first
two functions, one thread
0 mstime →
A: await fetch() then log. B: three quick logs. Press run and see who gets the thread when.

Back to the thread.

You now know why every database call, file read and API request in your app is prefixed with await. It's not a ritual. It's the event loop, spelled politely.