JavaScript - Fetch & AbortController
Overview
Estimated time: 35–45 minutes
Learn how to use fetch for HTTP requests, process JSON and text responses, detect and handle errors, set headers and bodies, and cancel requests with AbortController or timeouts.
Learning Objectives
- Perform GET and POST requests with
fetchand parseJSONsafely. - Check
response.okand throw descriptive errors on failure. - Pass headers and JSON bodies correctly.
- Cancel or timeout requests using
AbortControllerandPromise.racepatterns.
Prerequisites
GET JSON and error handling
async function getJSON(url) {
const res = await fetch(url);
if (!res.ok) {
throw new Error(`HTTP ${res.status} ${res.statusText}`);
}
return res.json();
}
// Usage
// const data = await getJSON('https://example.com/api');
POST JSON
async function postJSON(url, data) {
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
Abort and timeouts
// Abort with AbortController
async function fetchWithAbort(url, ms = 3000) {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), ms);
try {
const res = await fetch(url, { signal: ctrl.signal });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.text();
} finally {
clearTimeout(t);
}
}
// If supported, AbortSignal.timeout simplifies this:
// const res = await fetch(url, { signal: AbortSignal.timeout(3000) });
Retry with backoff (pattern)
async function retry(fn, { attempts = 3, baseMs = 200 } = {}) {
let lastErr;
for (let i = 0; i < attempts; i++) {
try { return await fn(); }
catch (e) {
lastErr = e;
if (i < attempts - 1) await new Promise(r => setTimeout(r, baseMs * 2**i));
}
}
throw lastErr;
}
// Usage:
// const json = await retry(() => getJSON('https://example.com/api'));
Common Pitfalls
- CORS: Requests to other origins may be blocked unless the server allows it.
- Body usage: Response bodies are streams; you can only read once (e.g.,
await res.json()then it's consumed). - Content-Type: Set
Content-Type: application/jsonwhen sending JSON; otherwise servers may not parse it. - Error detection:
fetchonly rejects on network errors. Useres.okor status checks to treat HTTP errors as failures.
Try it
Run to GET JSON, then attempt an aborting fetch with a short timeout. If network is blocked, you'll see error logs.