Content updated
By the end, you can…
- A fulfilled fetch is not proof of success. Check response.ok, parse the body, and validate its shape.
- Predict the example's result, change one part, and verify the behavior in your own script.
One idea at a time
An API is an interface provided for code to use. fetch is a browser API that asks for a resource at a URL and returns a promise for a Response object describing the server’s reply. HTTP is the request-and-response protocol used here. A GET request is the default and normally reads data. Fetch can reject for network problems, but an HTTP error such as 404 still gives you a Response. Check its ok property before treating the body as successful data.
Reading the body is another asynchronous step. response.json() parses it as JSON and can fail if the body is not valid JSON. After parsing, check the properties your interface needs. These are different layers of failure: reaching the server, getting a successful status, reading the format, and receiving the expected data.
What to remember first
A fulfilled fetch is not proof of success. Check response.ok, parse the body, and validate its shape.
Read the code before trying it
fetch("./learner.json")Request a resource- This relative URL resolves from the page location. Serve both files over a local HTTP server for this exercise.
response.ok / response.statusInspect HTTP success- ok is true for status codes 200 through 299. status gives the numeric code.
new Response(body, { status })Construct an offline response for practice- The previews use this browser object to test the same status and JSON-reading operations without contacting a server. It is not a fetch request.
await response.json()Parse the body- This returns a promise for parsed data. Read a response body only once unless you deliberately clone it.
throw new Error(message)Stop the success path- Throwing inside try lets catch handle an HTTP or validation failure consistently.
method, headers, bodyConfigure a request- For a JSON POST, choose method POST, a Content-Type header, and a JSON.stringify body. Only send to an endpoint intended to accept it.
CORSRespect cross-origin access- CORS means Cross-Origin Resource Sharing: the browser checks whether a remote server permits your page’s origin to read its response. no-cors is not a way to obtain readable JSON from a blocked response.
Walk through an example
async function loadLearner() {
try {
const response = await fetch("./learner.json");
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
if (!data || typeof data.name !== "string") {
throw new Error("Expected a learner name");
}
console.log(data.name);
} catch {
console.log("Could not load the learner. Check the URL and try again.");
}
}
loadLearner();Place learner.json beside the page with the contents shown below. On a local HTTP server, fetch reads that file. The code checks status before parsing and checks name before using it. Any of those failures goes to catch. The live comparison uses constructed Response objects, clearly labeled as simulations, so it makes no network calls.
See it happen: try a small change
Predict the result, choose a version, then compare the code and output. Try the controls when the example has them. Each version starts fresh.
Code to notice
// Offline simulation: construct a Response; no network request.
async function readSample() {
console.log("Checking response");
try {
const response = new Response("{\"name\":\"Mia\"}", { status: 200 });
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
if (!data || typeof data.name !== "string") {
throw new Error("Expected a name");
}
console.log(data.name);
} catch {
console.log("Could not use this response.");
}
}
readSample();Live result
What changed: Offline Response simulation: HTTP success, valid JSON, and a string name all pass.
Look a little closer
In DevTools Network, inspect the requested URL, status, and response body when a real request fails. A relative path can accidentally request your application's HTML fallback instead of JSON. A 200 response containing HTML still fails response.json, which is why status alone is insufficient. File URLs and cross-origin services have different restrictions from a same-origin local server.
A POST can send data for a server to process. The endpoint is the receiving URL; headers describe the request, Content-Type names its format, and body contains the data. Never paste private API keys into client JavaScript: visitors can inspect that code and its requests. Services that need secret credentials require a server-side endpoint. This lesson's local file exercise avoids accounts, credentials, and changes to an external service.
Open the project through HTTP
A local server lets the browser request files from your own computer. Open the project folder in your editor and start its local preview server if it has one. Use the http://localhost or http://127.0.0.1 address it gives you, not a file:// address. Keep index.html, script.js, and learner.json in the same folder for this example.
If Python 3 is already installed, another option is to open a terminal in that project folder and run the command below. Then open http://127.0.0.1:8000/ in the browser. Keep the terminal running while testing; press Ctrl+C there to stop it. This is only a local development server, not a deployment step.
python -m http.server 8000 --bind 127.0.0.1Create learner.json beside your page
{
"name": "Mia"
}Recognize a JSON POST request
This is an illustrative request shape, not an endpoint supplied by Tuklas. A server must implement /api/notes and validate its input before this can work. Do not run it against an unrelated site.
const response = await fetch("/api/notes", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: "Study fetch" }),
});
// Place inside an async function and check response.ok.Try it in your own project
Serve index.html, script.js, and learner.json from the same folder over HTTP using the Open the project through HTTP instructions. Open Developer Tools, choose Network, and reload to inspect learner.json. Restore valid JSON between each failure test so you change only one cause at a time.
The interactive preview runs in its own isolated document. Its Output panel mirrors console.log messages; it is not a full DevTools console. Choosing another version or resetting starts a fresh example and does not edit your local files. Read any simulation label: storage and request demonstrations explain their offline substitutes, while the written local examples use the real browser APIs.
A common wrong turn
Do not put all confidence in catch: fetch does not reject simply because the server returned 404 or 500. Check ok yourself. Do not use no-cors as a workaround; an opaque response cannot provide the readable JSON your application needs.
Your turn: request and check JSON with fetch
Load a small JSON file from your local project and show a useful fallback for three failure cases.
Try this in your own HTML and JavaScript files, then open the page in a browser. There is no separate checked practice for this task yet.
- Create learner.json with {"name":"Mia"} beside index.html and serve the folder over HTTP.
- Run the fetch example and inspect the request in DevTools Network. Expect Mia.
- Test a missing filename, malformed JSON, and valid JSON with no name. Each should reach your fallback instead of a misleading success message.
Go to the source
Examples are authored for Tuklas and checked with code and reference documentation. This is not a claim of independent human review. Suggest a correction.