← Over the wire · all materialsExercise 2 · 12 min · cases 1–3 in class
Act 2 · fetch

Load the market

Until today the stalls were an array typed into data.js. Now they come from the Harbour Market API: GET /api/stalls answers with a JSON array. Every editor here has a real-looking server behind it (the Network tab next to the console shows each request), and it restarts on every run. The API is documented in api.html.

The pattern. const response = await fetch(url) → check response.ok → await response.json(). Two awaits: the first gives you the status and headers, the second the body. These editors run a classic script, so there is no top-level await: use .then() or an async function.

1

From the server, not from the file

The market has ten stalls now. The page shows the three someone typed in.

Write loadStalls(): fetch /api/stalls and return the parsed body. Then render what it resolves to instead of the hard-coded array. card() and render(stalls) are done (🔒). Open the Network tab and click the request.

2

A 404 is not an exception

The page asked for a stall that doesn't exist and happily rendered an error message as if it were data.

fetch only rejects on a network failure. Make getJSON(url) reject with an Error for every status outside 200–299, with the status code and the server's message (from the error body) in its message: "404 No stall with the id …". Successful responses still resolve with the body.

3

Let the server filter

Clicking Food does nothing, and a request for ?tag=all would be a 400: the API doesn't know that tag.

Write stallsUrl(tag) with URLSearchParams: no query string for "all", ?tag=food otherwise. Then the click listener: press(tag), load that tag, render. getJSON from case 2 is in the locked part.

Homework · bonus

4 · bonus

Sort, too

The API sorts with ?sort=price, ?sort=-rating or ?sort=name. Add the select's value to the URL, combined with the tag, and re-load on change. The order of the cards is the server's order: don't sort in the browser.