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
fetch
and parseJSON
safely. - Check
response.ok
and throw descriptive errors on failure. - Pass headers and JSON bodies correctly.
- Cancel or timeout requests using
AbortController
andPromise.race
patterns.
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/json
when sending JSON; otherwise servers may not parse it. - Error detection:
fetch
only rejects on network errors. Useres.ok
or 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.