6.9 — Checkpoint: the Pokédex fetcher
Checkpoint. One function on the left — showPokemon — quietly contains the entire phase: the non-blocking thread (6.1) parking at awaits (6.6) while the event loop (6.2) and its express lane (6.5) shuttle promise reactions (6.4), a two-await fetch with its guard (6.7), errors falling into one catch (5.8 × async), and a finally that always signs off.
Every data-driven screen you've ever used — and every API test you'll ever write — is this exact flow: loading → data or error → done. Walk it once more with commentary, then build it twice with your own hands.
async function showPokemon(id) {
console.log("loading…");
try {
const res = await fetch(BASE + id);
if (!res.ok) {
throw new Error("HTTP " + res.status);
}
const p = await res.json();
console.log(p.name + " #" + p.id);
} catch (err) {
console.log("error: " + err.message);
} finally {
console.log("done");
}
}State one: "loading…" prints BEFORE any await — synchronously, instantly. Users (and test logs) should never stare at silence. Then the function parks at the first await, thread free, world turning.
The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”
Why fakes again in the exercises: determinism — the same reason professional test suites mock network calls. A test that depends on pokeapi.co's uptime and latency is a flaky test; a faked response with the same shape tests your logic with none of the randomness. Lesson 11.10 gives this practice its industrial name (route.fulfill); today you're already doing it.
The loading/error/done trio is also the anatomy of test-friendly UI: each state is observable — a spinner, an error banner, a rendered list. Playwright tests assert exactly these observations ("expect the spinner, then expect the list"). Apps built without visible states are the ones that are miserable to test — you'll say this in interviews someday.
Phase complete. The full picture, one breath. One thread. Blocking forbidden. The environment waits. Queue and express lane feed an empty stack. Promises are receipts. await parks frames. Combinators overlap independent waits. fetch rides it all. That paragraph is your teach-back — and a senior-engineer answer to "explain async JavaScript."
⌨️ part 1 — the fetcher that survives a 404
Build the full loading → error → done flow against a fake API that FAILS — your code must report the failure gracefully and always sign off.
requirements:
- A
fakeFetch(url)that resolves to{ ok: false, status: 404 }— the server couldn't find it. - An async
load(): print"loading…"; in atry, await the fetch, and if not ok, thrownew Error("HTTP " + status). - In the
catch, print"error: " + message; in afinally, print"done". Callload().
when you press RUN, the console must show exactly:
⌨️ part 2 — two pokémon, one wait
Fetch two records in PARALLEL from a fake API and print both names — using the start-first, all-second reflex from 6.8 and the two-await shape from 6.7.
requirements:
- A
fakeFetch(name)returning a promise of{ ok: true, json: () => Promise.resolve({ name }) }— it echoes the name you ask for. - An async
loadTwo(): START both fetches for"pikachu"and"squirtle"(no await yet!), then awaitPromise.allof the pair. - Await each response's
.json()(another all is fine), and print the two names, pikachu first.
when you press RUN, the console must show exactly:
✏️ Quick check 1
Type the FULL output, space-separated:
async function go() {
console.log("loading");
try {
const res = await Promise.resolve({ ok: false, status: 500 });
if (!res.ok) throw new Error("HTTP " + res.status);
console.log("data");
} catch (e) {
console.log(e.message);
} finally {
console.log("done");
}
}
go();✏️ Quick check 2
Ten independent fetches, ~100ms each. Roughly how many ms with start-first + Promise.all? Type the number.
✏️ Quick check 3
Test suites fake network responses instead of calling real APIs mainly for ___ — type the word (hint: the opposite of flaky).
🗣️ Now teach it back
The grand tour, out loud: explain how one JavaScript thread shows a loading spinner, fetches data from a server, handles a 404, and renders — naming every piece of machinery it rides on the way.
Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.