RECENTLY CHECKED
All projects →
Turn data into a physical briefing · STAGE 3 OF 4

Keep a display useful when a request fails

Put a request boundary around your status panel and preserve the last successful reading without presenting it as a new update.

You needA browser for fixture scenarios. Download both this file and the stage-two status function to run the reference together.

Reference checked 9 September 2026. Authored exercise; no physical build result is claimed.

Understand the change

  1. Separate data from transport

    The status function knows about readings; the adapter knows about requests. Passing fetcher in lets the same logic exercise saved fixtures before a real service is connected.

  2. Exercise four responses

    Compare a valid sample, HTTP 503, rejected request and malformed sample. Successful transport does not guarantee usable data. Try each with and without a previous reading.

  3. Preserve the observation time

    After failure, advance the clock. The retained reading must eventually become stale. A retry must not make the old sample look newly measured.

  4. Prepare the connection

    For a real provider, map its documented fields and units to the sample contract, choose an update interval from its terms and add a timeout/cancellation strategy. Keep private credentials out of public client files.

THE BRIEF

A focused request to try

Use this with a suitable AI assistant. Its response will vary; compare it with the checks below.

Use my readingStatus function to write an async adapter with an injected fetch function and endpoint argument. Check response.ok before parsing JSON. Reject invalid data. On failure preserve the last successful sample and label the update failure; never replace its measuredAt. Expose failure cases using fixtures. Use no API key or invented live endpoint.
THE REFERENCE

Worked reference example

Read the example, predict one change, then check the result.

// Place readingStatus from stage 2 above this function.
async function updateReading(fetcher, endpoint, previous, now) {
  try {
    const response = await fetcher(endpoint);
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    const sample = await response.json();
    const view = readingStatus(sample, now);
    if (view.state === "unavailable") throw new Error("Invalid reading");
    return {sample, ...view, update: "Received response"};
  } catch (error) {
    const view = readingStatus(previous, now);
    return {sample: previous ?? null, ...view,
      update: "Update failed; showing last valid sample if available"};
  }
}
const saved = {temperature:18, unit:"C", measuredAt:"2026-09-09T08:00:00Z"};
const offline = async () => { throw new Error("Offline"); };
const badHTTP = async () => ({ok:false, status:503});
const invalid = async () => ({ok:true, json:async () => ({temperature:"18"})});
// Fixture only: no request is sent to /sample.
updateReading(offline, "/sample", saved, Date.parse("2026-09-09T08:06:00Z"))
  .then(result => console.assert(result.state === "stale"));
TRY THE WORKING EXAMPLE

Run an update, then break it

These are labelled sample responses. The exercise makes no external requests.

Run the valid fixture first. Select a failure, move the clock to 360 seconds and run again. Then clear the sample and repeat the failure.

DISPLAY OUTPUTUnavailable

No successful sample retained.

Check your result

  • HTTP 503 and rejected requests both preserve an existing valid sample.
  • Malformed data never replaces the last valid sample.
  • Failure with no previous sample displays Unavailable.
  • A retained reading becomes stale as the example clock advances.

Where this can go wrong

The browser lab uses deterministic fixtures. The reference does not implement scheduling or a timeout and does not fetch live weather. Those choices depend on the provider and device.

Go to the source

MDN Using the Fetch API. Confirm current tool instructions before using them.

Tell us where this exercise was unclear