Skip to content
intermediate Phase 5 · JavaScript Async & DOM

Fetch API & HTTP Requests

Make HTTP requests with fetch, handle JSON, manage errors, and implement request aborting.

45m
0 problems
Topic Progress 0%

Request and Response Basics

Request and Response Basics

fetch(url) returns a Promise resolving to a Response — headers and body stream, not parsed JSON. Defaults: GET, credentials: 'same-origin', and it does not reject on HTTP errors; a 404 or 500 resolves with response.ok === false.

const res = await fetch('/api/items');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const items = await res.json();

The body can be consumed once — calling res.json() twice throws "body already used." Methods that send data set headers explicitly: Content-Type: application/json with JSON.stringify(body). fetch rejects only on network failure (offline, DNS, CORS block), which is a different branch from HTTP status handling.

Aborting and Retrying

Aborting and Retrying

A request you no longer need — user navigated away, a newer keystroke superseded it — should be aborted:

const ctrl = new AbortController();
search(url, { signal: ctrl.signal });
// on next keystroke:
ctrl.abort();
try { ... } catch (e) {
  if (e.name === 'AbortError') return;   // expected, not a failure
}

A timeout is the same primitive: setTimeout(() => ctrl.abort(), 5000). For retries, wrap in a helper that catches network errors, backs off with jitter, and only retries idempotent methods — retrying a POST can double-charge. Keep one controller per logical request; sharing a controller across parallel fetches aborts them all.

Pitfalls and CORS

Pitfalls and CORS

CORS failures surface as opaque network errors — check the .ok-independent rejection and the browser console for the preflight. Non-simple requests (custom headers, Content-Type: application/json) trigger an OPTIONS preflight; the server must answer it with the right Access-Control-Allow-* headers or the real request never runs.

Cookies cross-origin require credentials: 'include' and Access-Control-Allow-Credentials: true with an explicit origin (not *). Default redirect: 'follow' can mask a login page returned as 200 — inspect res.url or set redirect: 'manual' when that matters.

Interview: state that fetch rejects only on network errors, that you check res.ok for HTTP errors, and that one-shot bodies plus AbortController are the two mechanics most code gets wrong.

Quiz

1. What does fetch do when the server returns 500?

Question 1 options

2. Why does calling res.json() a second time fail?

Question 2 options

3. What triggers a CORS preflight OPTIONS request?

Question 3 options

Flashcards

Question

fetch error semantics

Answer

Rejects on network/CORS failure only; HTTP 4xx/5xx resolve with ok=false.

Question

response.ok

Answer

true for status 200–299 — the check every caller must perform.

Question

AbortController

Answer

signal aborts in-flight fetches; abort surfaces as AbortError (expected).

Question

One-shot body

Answer

res.json()/text() can be called once — clone() if you need both.

Question

Credentialed CORS

Answer

credentials: "include" + Allow-Credentials: true + explicit origin (never *).

Revision Notes

Key Takeaways

  • 1. Network errors reject; HTTP errors resolve — branch on both
  • 2. Abort superseded requests; back off retries for idempotent methods only
  • 3. Preflight and credentials rules explain most "works locally, fails in prod" CORS bugs

Interview Tips

  • • Write the error-handling shape out loud: try/catch for network, res.ok check for status, AbortError ignored
  • • Explain the preflight sequence when an interviewer mentions custom headers failing cross-origin

Cheat Sheet

fetch resolves 4xx/5xx → check res.ok; rejects only on network/CORS. Body readable once. AbortController for cancel/timeout; retry idempotent only. JSON body → preflight; cookies need credentials.

Continue Learning