Asynchronous JavaScriptLesson 4.5
Fetching data from APIs with fetch and handling errors
fetch API, Request Response objects, response.json, HTTP status codes, network errors vs HTTP errors, AbortController, headers, POST request, error handling pattern
fetch — The Browser's Built-In HTTP Client
fetch returns a Promise that resolves when the server responds — including for 4xx and 5xx status codes. A network failure (no connection, DNS error) rejects the Promise. An HTTP error status does not reject it. You must check both explicitly. This distinction is the single most common source of silent fetch bugs in production applications.
GET Request Pattern
async function getUser(id) {
const res = await fetch(`https://api.example.com/users/${id}`);
// fetch resolves for 404, 500, etc. — must check manually
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
}
return res.json(); // also returns a Promise
}
POST Request
async function createUser(data) {
const res = await fetch("https://api.example.com/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
if (!res.ok) throw new Error(`Failed: ${res.status}`);
return res.json();
}
Cancellation with AbortController
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.catch(err => {
if (err.name === "AbortError") console.log("Request cancelled");
else throw err;
});
// Cancel if no response within 3 seconds
setTimeout(() => controller.abort(), 3000);
Critical Pattern
Always check res.ok before calling res.json(). A 404 response body is perfectly valid JSON describing an error payload — without the check, you parse failure as success and wonder why the data looks wrong.
