APIs Web
Fetch API, Web Storage, IndexedDB, Web Workers y más APIs del navegador
APIs Web Esenciales
Los navegadores proporcionan potentes APIs que permiten a JavaScript interactuar con la red, almacenar datos, ejecutar tareas en segundo plano y acceder a funciones del dispositivo. Comprender estas APIs es esencial para construir aplicaciones web modernas.
APIs Cubiertas
- Fetch API — Solicitudes HTTP modernas
- Web Storage — localStorage y sessionStorage
- IndexedDB — Base de datos del lado del cliente
- Web Workers — Hilos en segundo plano
- Intersection Observer — Detección de visibilidad
Fetch API
// Solicitud GET básica
const response = await fetch("/api/users");
const users = await response.json();
// POST con cuerpo JSON
const newUser = await fetch("/api/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ name: "Alice", email: "alice@example.com" }),
});
// Ejemplo completo con manejo de errores
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Error HTTP: ${response.status}`);
}
const contentType = response.headers.get("content-type");
if (contentType?.includes("application/json")) {
return await response.json();
}
return await response.text();
} catch (error) {
if (error.name === "AbortError") {
console.log("La solicitud fue cancelada");
} else {
console.error("Fetch falló:", error);
}
throw error;
}
}
// Solicitud con timeout usando AbortController
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
return await response.json();
} finally {
clearTimeout(timeoutId);
}
}
Web Storage (localStorage y sessionStorage)
// localStorage - persiste entre sesiones del navegador
localStorage.setItem("theme", "dark");
const theme = localStorage.getItem("theme"); // "dark"
localStorage.removeItem("theme");
localStorage.clear(); // Eliminar todo
// Almacenar objetos (debe convertir a string)
const user = { name: "Alice", preferences: { theme: "dark" } };
localStorage.setItem("user", JSON.stringify(user));
const storedUser = JSON.parse(localStorage.getItem("user"));
// sessionStorage - se borra cuando se cierra la pestaña
sessionStorage.setItem("tempData", "value");
// Wrapper de almacenamiento con expiración
const storage = {
set(key, value, ttlMs) {
const item = {
value,
expiry: ttlMs ? Date.now() + ttlMs : null,
};
localStorage.setItem(key, JSON.stringify(item));
},
get(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) return null;
const item = JSON.parse(itemStr);
if (item.expiry && Date.now() > item.expiry) {
localStorage.removeItem(key);
return null;
}
return item.value;
}
};
storage.set("cache", data, 3600000); // 1 hora de TTL
IndexedDB
// Abrir base de datos
const request = indexedDB.open("MyDatabase", 1);
request.onerror = () => console.error("Error de BD");
request.onupgradeneeded = (event) => {
const db = event.target.result;
// Crear almacén de objetos (tabla)
const store = db.createObjectStore("users", { keyPath: "id" });
store.createIndex("email", "email", { unique: true });
};
request.onsuccess = (event) => {
const db = event.target.result;
// Agregar datos
const transaction = db.transaction(["users"], "readwrite");
const store = transaction.objectStore("users");
store.add({ id: 1, name: "Alice", email: "alice@example.com" });
// Leer datos
const getRequest = store.get(1);
getRequest.onsuccess = () => console.log(getRequest.result);
};
Web Workers
// main.js - Crear y comunicarse con el worker
const worker = new Worker("worker.js");
// Enviar datos al worker
worker.postMessage({ type: "calculate", data: [1, 2, 3, 4, 5] });
// Recibir resultados
worker.onmessage = (event) => {
console.log("Resultado:", event.data);
};
// worker.js - Hilo en segundo plano
self.onmessage = (event) => {
const { type, data } = event.data;
if (type === "calculate") {
// Cálculo pesado sin bloquear el hilo principal
const result = data.reduce((sum, n) => sum + n, 0);
self.postMessage(result);
}
};
Intersection Observer
// Detectar cuándo los elementos entran al viewport
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
if (entry.target.dataset.src) {
entry.target.src = entry.target.dataset.src;
observer.unobserve(entry.target);
}
}
});
}, {
threshold: 0.1,
rootMargin: "50px"
});
document.querySelectorAll(".lazy-image").forEach((img) => {
observer.observe(img);
});
💡 Puntos Clave
- • Usa Fetch API con async/await para solicitudes de red
- • localStorage persiste; sessionStorage se borra al cerrar la pestaña
- • IndexedDB para datos grandes/estructurados del lado del cliente
- • Web Workers para cálculos pesados sin bloquear la UI
- • Intersection Observer para carga diferida y efectos de scroll
- • Siempre maneja errores y verifica el soporte de las APIs