JavaScript Notes
Master JavaScript
Introduction
The Fetch API is the modern, Promise-based way to make HTTP requests in JavaScript. It replaced the old XMLHttpRequest (XHR) with a cleaner, more flexible interface. Introduced in 2015 and now available in all modern browsers and Node.js 18+.
Why Fetch over XMLHttpRequest?
- Returns Promises — works perfectly with
async/await - Cleaner, more readable syntax
- Built-in JSON support
- Easier to configure headers, methods, and body
- Supports streaming responses
How Fetch Works Internally
Basic Fetch — GET Request
With Promises (.then)
Status: 200 OK: true Title: sunt aut facere repellat provident occaecati excepturi optio Body: quia et suscipit suscipit recusandae consequuntur expedita...
With async/await (Cleaner)
async function getPost(id) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
const post = await response.json();
console.log(`Post #${post.id}: ${post.title}`);
return post;
} catch (error) {
console.error("Failed:", error.message);
}
}
getPost(1);Post #1: sunt aut facere repellat provident occaecati excepturi optio
The Response Object
The Response object contains everything about the HTTP response:
async function inspectResponse() {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
// Status information
console.log("status:", response.status); // 200
console.log("statusText:", response.statusText); // "OK"
console.log("ok:", response.ok); // true (200-299)
// Headers
console.log("Content-Type:", response.headers.get("content-type"));
// "application/json; charset=utf-8"
// URL
console.log("url:", response.url);
// Body (can only be read ONCE)
const data = await response.json();
console.log("data:", data.title);
}
inspectResponse();status: 200 statusText: OK ok: true Content-Type: application/json; charset=utf-8 url: https://jsonplaceholder.typicode.com/posts/1 data: sunt aut facere repellat provident occaecati excepturi optio
Body Reading Methods:
const response = await fetch(url);
// For JSON data
const json = await response.json();
// For plain text
const text = await response.text();
// For binary data (images, files)
const blob = await response.blob();
// For form data
const formData = await response.formData();
// For raw binary (ArrayBuffer)
const buffer = await response.arrayBuffer();
// ⚠️ Important: Body can only be read ONCE!
// After calling .json(), you cannot call .text() on the same responsePOST Request — Sending Data
async function createPost(postData) {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST", // HTTP method
headers: {
"Content-Type": "application/json", // Tell server we're sending JSON
"Authorization": "Bearer my-token-here" // Auth header (optional)
},
body: JSON.stringify(postData) // Convert object to JSON string
});
if (!response.ok) {
throw new Error(`HTTP Error: ${response.status}`);
}
const createdPost = await response.json();
console.log("Created post ID:", createdPost.id);
console.log("Title:", createdPost.title);
return createdPost;
} catch (error) {
console.error("Create failed:", error.message);
}
}
createPost({
title: "My First Post",
body: "This is the content of my post",
userId: 1
});Created post ID: 101 Title: My First Post
Other HTTP Methods — PUT, PATCH, DELETE
// PUT — Replace entire resource
async function updatePost(id, data) {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
const updated = await response.json();
console.log("Updated:", updated.title);
return updated;
}
// PATCH — Update specific fields
async function patchPost(id, changes) {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(changes)
});
const patched = await response.json();
console.log("Patched title:", patched.title);
return patched;
}
// DELETE — Remove resource
async function deletePost(id) {
const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, {
method: "DELETE"
});
console.log("Deleted, status:", response.status); // 200
return response.ok;
}
// Usage
await updatePost(1, { title: "New Title", body: "New body", userId: 1 });
await patchPost(1, { title: "Just updating the title" });
await deletePost(1);Updated: New Title Patched title: Just updating the title Deleted, status: 200
Error Handling — The Important Gotcha!
⚠️ Fetch does NOT throw on HTTP errors (404, 500, etc.)! It only throws on network failures.
// ❌ Wrong: This does NOT catch 404 or 500 errors
async function wrongErrorHandling() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/99999");
const data = await response.json(); // Runs even for 404!
console.log(data); // {} — empty object from 404 response
} catch (error) {
// This only catches NETWORK errors (DNS failure, offline, etc.)
console.error("Network error:", error);
}
}
// ✅ Correct: Always check response.ok
async function correctErrorHandling() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/99999");
// Manually check for HTTP errors
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
if (error.name === "TypeError") {
console.error("Network failure:", error.message);
} else {
console.error("HTTP Error:", error.message);
}
}
}
correctErrorHandling(); // "HTTP 404: Not Found"HTTP 404: Not Found
A Reusable Fetch Wrapper
Post: sunt aut facere repellat provident occaecati excepturi optio Created ID: 101
AbortController — Cancelling Requests
Got: sunt aut facere repellat provident occaecati excepturi optio
Parallel Fetch with Promise.all
dashboard: ~250ms User: Leanne Graham Posts: 10 Todos: 20 (11 done)
Common Mistakes ⚠️
Mistake 1: Forgetting to await response.json()
// ❌ Wrong: data is a Promise, not the actual data
async function wrong() {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = response.json(); // Missing await!
console.log(data.title); // undefined — data is a Promise!
}
// ✅ Correct
async function correct() {
const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await response.json(); // Await the body reading too!
console.log(data.title); // ✅ Works
}Mistake 2: Not Checking response.ok
// ❌ Fetch DOES NOT throw on 404/500
const response = await fetch("/nonexistent");
const data = await response.json(); // This runs even for 404!
// ✅ Always check
if (!response.ok) throw new Error(`HTTP ${response.status}`);Mistake 3: Reading Response Body Twice
// ❌ Body can only be read once!
const response = await fetch(url);
const text = await response.text();
const json = await response.json(); // TypeError: body stream already read
// ✅ Read once, then use
const response2 = await fetch(url);
const json2 = await response2.json();Mistake 4: Sending JSON Without Content-Type Header
// ❌ Server may not know it's receiving JSON
await fetch(url, {
method: "POST",
body: JSON.stringify(data) // Missing header!
});
// ✅ Always set Content-Type for JSON
await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" }, // Required!
body: JSON.stringify(data)
});Interview Questions 🎯
Q1. What does fetch() return?
fetch()returns aPromise<Response>. The Promise resolves to aResponseobject when the server sends headers. The response body (actual data) must be read separately usingresponse.json(),response.text(), etc. — each of which also returns a Promise.
Q2. Does fetch() throw an error on a 404 or 500 response?
No! This is a common gotcha.fetch()only rejects its Promise for network failures (no connection, DNS failure, CORS error). For HTTP errors like 404 or 500, the Promise resolves normally. You must manually checkresponse.ok(true for status 200-299) and throw an error yourself.
Q3. What is the difference between fetch() and XMLHttpRequest?
fetch()uses Promises (chainable, async/await compatible), has a cleaner API, supports streaming, and is more composable.XMLHttpRequestuses callbacks and has a more complex, event-based API.fetch()doesn't support upload progress events or synchronous requests (which is actually good!).
Q4. How do you cancel a fetch() request?
UseAbortController: create a controller, pass itssignalto fetch, and callcontroller.abort()to cancel. If aborted, the fetch Promise rejects with anAbortError.
Q5. How do you set request headers in fetch()?
Pass aheadersoption in the second argument:fetch(url, { headers: { "Content-Type": "application/json", "Authorization": "Bearer token" } }). You can also use theHeadersconstructor:new Headers({ "Content-Type": "application/json" }).
Q6. How do you make a POST request with fetch()?
``javascript fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(dataObject) }) ``Q7. Why does fetch() require two await calls for JSON?
The firstawait fetch(url)waits for the response headers (the server's initial reply). The response body arrives separately as a stream.await response.json()waits for the full body to be received and parsed. This design supports streaming large responses efficiently.
Key Takeaways 📌
fetch()returns aPromise<Response>— the response body is a separate stream- Always
await response.json()(or.text()) to read the body — it's async too fetch()does NOT throw on 404/500 — checkresponse.okmanually- Use
AbortControllerto cancel requests (timeouts, component unmount) - Set
Content-Type: application/jsonheader when sending JSON data - Use
Promise.all()for parallel requests — much faster than sequential - The response body can only be read once — it's a stream
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JavaScript Fetch API - Complete Guide with Examples, Error Handling & Async/Await.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this JavaScript Master Course topic.
Search Terms
javascript-complete-guide, javascript master course, javascript, complete, guide, asynchronous, fetch, api
Related JavaScript Master Course Topics