← Build · all briefsEveryone · 45 min · individually
Build · step 1

Connect the market

The market from Lecture 5 still reads its vendors from js/data.js, typed by hand. The course server has the real list, with two more stalls and their ratings, and you have your own copy of it. Connect the two: every request through one module, the stalls in state, and a page that says what's happening while the data is on its way, or when it doesn't arrive.

“The website says eight stalls. The market has ten.”

Done means: localhost:8080 shows ten vendors with ratings, loaded with one GET …/api/stalls from your market. The course server fails about 1 request in 10 with a 500 on purpose, so the error path runs even without chaos. With chaos on (harbour-api.lopin.me), a reload shows "Loading the vendors…", a failed one shows a sentence and a Try again button that recovers, and the console has no Uncaught. data.js is deleted.

Set up (5 minutes)

  1. Fork github.com/nlopin/harbour-market-starter on GitHub, clone your fork, and create a branch: git switch -c connect-the-market.
  2. Open harbour-api.lopin.me, type your GitHub username, press Check. Copy your API's URL into API at the top of starter/js/api.js.
  3. In the repository's folder: npm start (live-server, through npx; no npm install). Open http://localhost:8080: eight vendors, typed by hand.
  4. DevTools → Network → Fetch/XHR: no requests yet. Keep it open. Your code goes in starter/.
  5. Keep api.html and the cheat sheet in other tabs.

The steps (tick as you go)

Each step says how you know it works. Check before moving on.

1 · api.js

  • HttpError: name, a message with the status and the server's message, status and body on it.
  • request(method, path, data, options): fetch(API + path, …); a JSON body and its Content-Type when there is data; on a non-2xx, read the error body (ignore it if it isn't JSON) and throw an HttpError; null for a 204; otherwise the parsed body.
  • describe(error): a short sentence for people, from the error's status or name.
  • Check, in the console: const api = await import("/js/api.js"), then await api.getJSON("/stalls") gives 10 stalls and await api.getJSON("/stalls/pizza") rejects with an error whose status is 404.

2 · state and loading

  • state gets status ("loading" · "ready" · "error"), error and stalls: []. visibleStalls() and render() read state.stalls.
  • loadStalls() in main.js: loading, render, request, ready or error, render. Started with a top-level await.
  • Nothing imports data.js: delete it.
  • Check: ten vendors, Brass & Bones included; one GET /api/stalls in the Network panel; the filters, the search and the ♥ still work.

3 · what people see

  • A status line (a live region already in the HTML): "Loading the vendors…", then "10 stalls".
  • An error: a sentence in a role="alert" element that stays in the page, and a Try again button that's hidden unless there's an error. Try again moves focus to the status line, then calls loadStalls().
  • Each card shows its rating: ★ 4.7 · 3 reviews, or "no reviews yet".
  • Check with chaos on (harbour-api.lopin.me: 1.2 s, 30 %): reload five times. Loading, failure and recovery all look right; nothing Uncaught.

Edge cases (minutes 36–42)

Stuck? One hint at a time

Network panel first: is the request sent, with what, and what came back? Then the console. Then a hint.

Hint 1

Which modules import stalls from data.js today, and what should each of them read instead?

Hint 2

render() runs before the stalls arrive. What should it draw when state.stalls is empty because they're still loading, and when it's empty because the market has no stalls?

Hint 3

Which of the four failure modes from slide "How a request fails" can loadStalls() meet, and which line of your code turns each one into state.status = "error"?

Hint 4

The error message and the Try again button: which of them must stay in the page all the time, and why?

Traps

Open when something behaves strangely

The 45 minutes

0–5 · runFork, clone, your API's URL, npm start, Network panel open.
5–12 · api.jsAt 12: the console check of step 1 passes.
12–30 · stateStep 2, then step 3's status line and error.
30–42 · finishRatings, chaos on, the edge cases.
42–45 · PRCommit, push, open a pull request. Done early? Pick a brief.

Hand it in

Push your branch to your fork and open a pull request against harbour-market-starter's main. In the description: what works, what doesn't yet, and how you tested it with chaos on. A PR that's still in progress is fine: mark it as a draft and finish it at home.

Done early?

Pick one of the briefs: they all start from a connected market. A new branch on top of this one, a second pull request; start its core in class, finish at home, demo next class.