Fetch API & HTTP Requests
📖 Concept
The Fetch API provides a modern, Promise-based way to make HTTP requests. It replaces the older XMLHttpRequest.
fetch(url, options) returns a Promise that resolves to a Response object.
Key points:
fetchonly rejects on network errors, NOT on HTTP errors (4xx, 5xx)- You must check
response.okorresponse.statusfor HTTP errors - Response body can be read ONCE:
.json(),.text(),.blob(),.arrayBuffer()
🏠 Real-world analogy: fetch is like sending a letter (request) and waiting for a reply (response). The postal service (network) delivers it. You might get a reply saying "denied" (404/500), but the delivery itself succeeded — that's why fetch doesn't reject on HTTP errors.
💻 Code Example
1// GET request2async function getUsers() {3 const response = await fetch("https://jsonplaceholder.typicode.com/users");4 if (!response.ok) throw new Error(`HTTP ${response.status}`);5 return response.json();6}78// POST request9async function createUser(userData) {10 const response = await fetch("https://api.example.com/users", {11 method: "POST",12 headers: {13 "Content-Type": "application/json",14 "Authorization": "Bearer token123"15 },16 body: JSON.stringify(userData)17 });18 if (!response.ok) {19 const error = await response.json();20 throw new Error(error.message);21 }22 return response.json();23}2425// PUT, PATCH, DELETE26async function updateUser(id, data) {27 return fetch(`/api/users/${id}`, {28 method: "PUT",29 headers: { "Content-Type": "application/json" },30 body: JSON.stringify(data)31 });32}3334async function deleteUser(id) {35 return fetch(`/api/users/${id}`, { method: "DELETE" });36}3738// Reusable API client39class ApiClient {40 constructor(baseURL, token) {41 this.baseURL = baseURL;42 this.token = token;43 }44 async request(endpoint, options = {}) {45 const url = `${this.baseURL}${endpoint}`;46 const res = await fetch(url, {47 ...options,48 headers: {49 "Content-Type": "application/json",50 "Authorization": `Bearer ${this.token}`,51 ...options.headers52 }53 });54 if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);55 return res.json();56 }57 get(endpoint) { return this.request(endpoint); }58 post(endpoint, data) {59 return this.request(endpoint, {60 method: "POST", body: JSON.stringify(data)61 });62 }63}6465// Abort a request66const controller = new AbortController();67setTimeout(() => controller.abort(), 5000); // Cancel after 5s68try {69 const res = await fetch("/api/data", { signal: controller.signal });70} catch (err) {71 if (err.name === "AbortError") console.log("Request cancelled");72}
🏋️ Practice Exercise
Mini Exercise:
- Build a function that fetches data with timeout using AbortController
- Create an API wrapper class with get, post, put, delete methods
- Implement request caching — don't re-fetch if data was fetched within last 5 minutes
- Build a simple data fetching hook with loading, error, and data states
⚠️ Common Mistakes
fetchdoes NOT reject on HTTP errors (404, 500) — it only rejects on network failures. Always checkresponse.ok!Reading the response body twice —
.json(),.text()etc. can only be called ONCE. Clone withresponse.clone()if neededForgetting
Content-Type: application/jsonheader for POST/PUT requestsNot handling the AbortError when using AbortController — it's a normal error that should be caught
Sending credentials (cookies) —
fetchdoesn't send cookies by default for cross-origin. Usecredentials: 'include'
💼 Interview Questions
🎤 Mock Interview
Mock interview is powered by AI for Fetch API & HTTP Requests. Login to unlock this feature.