js/utils.js + js/api.js — the helper and the network layer
Two files in the code column, as tabs: js/utils.js (a small modify — one new helper) and js/api.js (new). The rule for api.js: only this file talks to the API. The rest of the app calls fetchPictures(days) and knows nothing about fetch, URLs or keys. One layer — change the API once and nothing else needs touching.
fetchPictures works out the date range, builds the URL with the key, and calls a shared request(). request() is the single place a response is checked.
First, the utils.js tab — one date helper api.js needs (the API expects YYYY-MM-DD). Everything else in the file stays; the diff shows just this addition:
/** Date → "YYYY-MM-DD" (the format the NASA API expects) */
export function formatDateParam(date) {
return date.toISOString().split('T')[0];
}
The heart of it — request():
async function request(url) {
const response = await fetch(url);
if (!response.ok) { // ← WITHOUT THIS, an error passes silently
throw new Error(`The API returned ${response.status}`);
}
return response.json();
}
response.ok is true for status 200–299. If the server returns a 404 or 500, fetch does not throw — await fetch(...) just returns a response with ok === false. If you don't check and go straight to response.json(), you'll try to parse an error page (often HTML) as JSON and get a cryptic "Unexpected token <" error.
Tip. Why
data.reverse()at the end? NASA returns pictures oldest-first. In the gallery we want newest on top, so we flip it. A small thing, but these "data tidyings" belong in the API layer — the rest of the app receives the order already sorted.