JavaScript — Fetch
One function for the network
const res = await fetch("https://api.github.com/users/octocat");
fetch returns a promise resolving to a Response object — headers arrived, body maybe not yet.
Reading JSON (two-step!)
const res = await fetch(url);
const data = await res.json(); // parse body → JS value
console.log(data.name);
.json() is also async (body streams in). Sibling methods: .text(), .blob() for files.
The #1 gotcha: fetch only rejects on network failure. A 404 or 500 still resolves! Check manually:
if (!res.ok) { // status outside 200–299
throw new Error(`HTTP ${res.status}`);
}
Wrap it once, reuse forever:
async function getJSON(url) {
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
Sending data — POST
const res = await fetch("/api/todos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: "Learn fetch", done: false }),
});
| Method | Intent |
|---|---|
| GET | read (default) |
| POST | create |
| PUT/PATCH | update |
| DELETE | remove |
JSON bodies must be stringified and declared via Content-Type — the two most-forgotten lines in web dev.
Full CRUD sketch
async function crudDemo() {
// CREATE
const created = await getJSON("/api/todos", {
method: "POST", body: JSON.stringify({ title: "new" })
});
// READ one
await getJSON(`/api/todos/${created.id}`);
// UPDATE
await fetch(`/api/todos/${created.id}`, {
method: "PATCH",
body: JSON.stringify({ done: true })
});
// DELETE
await fetch(`/api/todos/${created.id}`, { method: "DELETE" });
}
Loading states & UI pattern
list.innerHTML = "Loading…";
try {
const todos = await getJSON("/api/todos");
list.innerHTML = todos.map(t => `<li>${t.title}</li>`).join("");
} catch (e) {
list.textContent = `Couldn't load: ${e.message}`;
} finally {
spinner.hidden = true;
}
Every real app: loading → success/error UI. Plan all three states before coding the request.
Headers, auth & query params
fetch(url, { headers: { Authorization: `Bearer ${token}` } });
// building query strings safely:
const qs = new URLSearchParams({ page: 2, q: "js" });
fetch(`https://x.dev/search?${qs}`);
// https://x.dev/search?page=2&q=js ← encoded automatically
CORS in one paragraph
Browsers block reading cross-origin responses unless that server sends permissive headers (Access-Control-Allow-Origin). When your fetch mysteriously errors while curl works — it's CORS, a server-side fix, not your bug.
Mini Practice
- Fetch GitHub API user; print name/avatar with full error handling
- POST to jsonplaceholder.typicode.com; log returned fake id
- Build getJSON wrapper; prove it throws on a 404 URL
- Paginate with URLSearchParams; fetch pages 1-3 sequentially
- Wire loading/error/success states around any public API
Next: window → (browser APIs stretch)
Related Topics
Frequently Asked Questions about Fetch
What is Fetch in JavaScript?
Fetch is a fundamental concept in JavaScript. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Fetch?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Fetch.
Why is Fetch important in JavaScript?
Fetch is essential for JavaScript development. Understanding this concept will help you write better code and solve real-world problems more effectively.