Browser APIs
localStorage, fetch, IntersectionObserver, Web Workers, and other powerful built-in browser features
Last updated on
Browsers provide powerful APIs beyond the DOM. Knowing these separates frontend developers from frontend engineers.
Storage APIs
localStorage / sessionStorage
// localStorage — persists until explicitly cleared
localStorage.setItem("theme", "dark");
localStorage.getItem("theme"); // "dark"
localStorage.removeItem("theme");
localStorage.clear(); // remove everything
// sessionStorage — cleared when tab closes
sessionStorage.setItem("token", "abc123");
// Store objects (must stringify)
const user = { name: "Shiva", role: "admin" };
localStorage.setItem("user", JSON.stringify(user));
const saved = JSON.parse(localStorage.getItem("user"));| Feature | localStorage | sessionStorage | Cookies |
|---|---|---|---|
| Size | ~5-10MB | ~5-10MB | ~4KB |
| Persists | Until cleared | Until tab closes | Configurable (expires) |
| Sent to server | No | No | Yes (every request!) |
| Access | Same origin | Same origin + tab | Same origin |
Fetch API
// GET request
const response = await fetch("https://api.example.com/users");
const users = await response.json();
// POST request
const newUser = await fetch("https://api.example.com/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "Shiva", email: "shiva@example.com" })
});
// Error handling — fetch doesn't throw on HTTP errors!
const response = await fetch("/api/data");
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}AbortController — Cancel Requests
const controller = new AbortController();
// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch("/api/slow", {
signal: controller.signal
});
} catch (error) {
if (error.name === "AbortError") {
console.log("Request was cancelled");
}
}IntersectionObserver — Detect Visibility
Efficiently detect when elements enter or leave the viewport:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
// Lazy load images
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img); // stop watching
}
});
}, { threshold: 0.1 }); // trigger at 10% visibility
// Observe elements
document.querySelectorAll(".lazy-img").forEach(img => {
observer.observe(img);
});Use cases: Lazy loading images, infinite scroll, analytics (track what users see), animation on scroll.
MutationObserver — Watch DOM Changes
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
console.log("DOM changed:", mutation.type);
});
});
observer.observe(document.body, {
childList: true, // watch for added/removed children
subtree: true, // watch all descendants
attributes: true // watch attribute changes
});
// Stop watching
observer.disconnect();Web Workers — Background Threads
Run CPU-intensive code without blocking the UI:
// main.js
const worker = new Worker("worker.js");
worker.postMessage({ data: largeArray });
worker.onmessage = (event) => {
console.log("Result:", event.data);
};
// worker.js
self.onmessage = (event) => {
const result = heavyComputation(event.data);
self.postMessage(result);
};Other Useful APIs
URL & URLSearchParams
const url = new URL("https://example.com/search?q=hello&page=1");
url.searchParams.get("q"); // "hello"
url.searchParams.set("page", "2");
url.toString(); // "https://example.com/search?q=hello&page=2"Clipboard API
// Copy
await navigator.clipboard.writeText("Copied text!");
// Paste
const text = await navigator.clipboard.readText();Notification API
if (Notification.permission === "granted") {
new Notification("Hello!", { body: "You have a new message" });
} else {
Notification.requestPermission();
}FormData
const form = document.querySelector("form");
const formData = new FormData(form);
const data = Object.fromEntries(formData); // { name: "...", email: "..." }