Skip to main content

Web APIs: Fetch, localStorage, Timers


Fetch API

// Basic GET request
fetch("https://api.example.com/users")
.then(res => {
if (!res.ok) throw new Error(`HTTP error: ${res.status}`);
return res.json();
})
.then(data => console.log(data))
.catch(err => console.error(err));

// With async/await
async function getUsers() {
const res = await fetch("https://api.example.com/users");
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
}

// POST request
const createUser = async (userData) => {
const res = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer TOKEN"
},
body: JSON.stringify(userData)
});
return await res.json();
};

// PUT / PATCH / DELETE
await fetch(`/api/users/${id}`, { method: "DELETE" });
await fetch(`/api/users/${id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "New Name" })
});

// Response methods
response.json(); // parse JSON body
response.text(); // get as text
response.blob(); // get as Blob (files/images)
response.formData(); // get as FormData
response.status; // 200, 404, 500...
response.ok; // true for 200-299
response.headers.get("Content-Type");

localStorage and sessionStorage

// localStorage: persists across browser sessions
localStorage.setItem("token", "abc123");
localStorage.getItem("token"); // "abc123"
localStorage.removeItem("token");
localStorage.clear(); // remove all
localStorage.length; // number of items

// sessionStorage: cleared when tab/window closes
sessionStorage.setItem("cart", JSON.stringify([{id:1}]));
const cart = JSON.parse(sessionStorage.getItem("cart"));

// Both only store STRINGS — use JSON for objects
localStorage.setItem("user", JSON.stringify({ name: "Reet", role: "dev" }));
const user = JSON.parse(localStorage.getItem("user"));

// Utility wrapper
const storage = {
get: (key) => JSON.parse(localStorage.getItem(key)),
set: (key, value) => localStorage.setItem(key, JSON.stringify(value)),
remove: (key) => localStorage.removeItem(key)
};

Timers

// setTimeout: run ONCE after delay (milliseconds)
const timerId = setTimeout(() => {
console.log("Runs after 2 seconds");
}, 2000);

// Cancel before it fires
clearTimeout(timerId);

// setInterval: run REPEATEDLY at interval
const intervalId = setInterval(() => {
console.log("Runs every second");
}, 1000);

// Stop the interval
clearInterval(intervalId);

// Self-stopping interval
let count = 0;
const id = setInterval(() => {
console.log(count++);
if (count >= 5) clearInterval(id);
}, 1000);

// Promise-based delay
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
await sleep(2000); // pause 2 seconds in async function

// requestAnimationFrame (~60fps for smooth animations)
function animate(timestamp) {
element.style.left = (timestamp / 10 % 300) + "px";
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

URL and URLSearchParams

const url = new URL("https://example.com:3000/path?q=hello&page=2#section");
url.protocol; // "https:"
url.hostname; // "example.com"
url.port; // "3000"
url.pathname; // "/path"
url.search; // "?q=hello&page=2"
url.hash; // "#section"
url.searchParams.get("q"); // "hello"
url.searchParams.set("page", 3);
url.searchParams.append("sort", "asc");
url.toString(); // full URL with modifications

History API

history.pushState({ page: 2 }, "", "/page-2");    // add to history
history.replaceState({ page: 2 }, "", "/page-2"); // replace current
history.back(); // go back
history.forward(); // go forward
history.go(-2); // go back 2 pages

window.addEventListener("popstate", (e) => {
console.log(e.state);
});

Intersection Observer

// Detect when elements enter/exit the viewport
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
observer.unobserve(entry.target); // stop observing
}
});
}, {
threshold: 0.1, // 10% visible to trigger
rootMargin: "0px 0px -100px 0px"
});

document.querySelectorAll(".lazy").forEach(el => observer.observe(el));

MCQ — Web APIs

Q1: When does response.ok return true?

A) Always B) Only for status 200 C) For status codes 200–299 ✅ D) For all non-error responses (200–399)

Answer: C

Q2: What is the difference between localStorage and sessionStorage?

A) localStorage is faster B) localStorage persists indefinitely; sessionStorage is cleared when the tab closes ✅ C) sessionStorage has more storage space D) localStorage stores objects, sessionStorage stores strings

Answer: B — Both store strings only and have similar 5-10MB limits.

Q3: Does fetch throw an error on a 404 response?

A) Yes, automatically B) No — you must check response.ok or response.status manually ✅ C) Only in strict mode D) Depends on the server

Answer: Bfetch only rejects on network failures, not HTTP errors like 404/500.

Q4: What does clearTimeout(id) do?

A) Clears all timeouts B) Cancels a specific pending timeout before it fires ✅ C) Resets the timeout timer D) Pauses the timeout

Answer: B

Q5: How do you store an object in localStorage?

A) localStorage.setItem("key", obj) B) localStorage.setObject("key", obj) C) localStorage.setItem("key", JSON.stringify(obj))D) localStorage.set("key", obj)

Answer: C — localStorage only stores strings. Must serialize/deserialize with JSON.