Volver a JavaScript Intermedio

Web APIs y Almacenamiento en el Navegador

Los navegadores modernos exponen APIs integradas muy potentes. Este capítulo cubre las más útiles para construir aplicaciones reales.

Fetch API

// GET básico const response = await fetch('/api/usuarios'); const usuarios = await response.json(); // POST con cuerpo JSON const nuevoUsuario = await fetch('/api/usuarios', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nombre: 'Ana', rol: 'admin' }), }).then(r => r.json()); // Wrapper robusto de fetch async function apiFetch(url, opciones = {}) { const response = await fetch(url, { headers: { 'Content-Type': 'application/json', ...opciones.headers }, ...opciones, }); if (!response.ok) { const error = await response.json().catch(() => ({ message: response.statusText })); throw new Error(error.message ?? `HTTP ${response.status}`); } return response.status === 204 ? null : response.json(); }

Almacenamiento en el Navegador

// localStorage — persiste entre sesiones localStorage.setItem('tema', 'oscuro'); const tema = localStorage.getItem('tema'); // 'oscuro' localStorage.removeItem('tema'); localStorage.clear(); // Guardar objetos (hay que serializar) const preferencias = { tema: 'oscuro', fuente: 16 }; localStorage.setItem('prefs', JSON.stringify(preferencias)); const cargadas = JSON.parse(localStorage.getItem('prefs') ?? '{}'); // sessionStorage — se borra al cerrar la pestaña sessionStorage.setItem('tokenTemporal', 'abc123');
localStoragesessionStorageCookies
Capacidad~5 MB~5 MB~4 KB
PersistePara siempreSesión de pestañaConfigurable
Se envía al servidor

Intersection Observer

Detecta cuando los elementos entran/salen del viewport (carga diferida, scroll infinito, animaciones):

const observer = new IntersectionObserver( (entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); // Opcionalmente dejar de observar tras la primera aparición observer.unobserve(entry.target); } }); }, { threshold: 0.1 } // 10% visible activa el callback ); document.querySelectorAll('.animar-al-aparecer').forEach(el => observer.observe(el));

Web Workers

Ejecuta código costoso en CPU fuera del hilo principal para mantener la UI fluida:

// worker.js self.onmessage = function ({ data }) { // Cálculo costoso const resultado = data.reduce((suma, n) => suma + n, 0); self.postMessage(resultado); }; // main.js const worker = new Worker('worker.js'); worker.postMessage([1, 2, 3, 4, 5]); worker.onmessage = ({ data }) => { console.log('Suma:', data); // Suma: 15 worker.terminate(); };

URL y URLSearchParams

const url = new URL('https://ejemplo.com/buscar?q=js&pagina=2'); url.hostname; // 'ejemplo.com' url.pathname; // '/buscar' url.searchParams.get('q'); // 'js' url.searchParams.get('pagina'); // '2' // Construir query strings de forma segura (maneja codificación) const params = new URLSearchParams({ q: 'hola mundo', pagina: 1 }); params.toString(); // 'q=hola+mundo&pagina=1'

API del Portapapeles

// Escribir await navigator.clipboard.writeText('¡Texto copiado!'); // Leer const texto = await navigator.clipboard.readText(); // Botón de copiar práctico async function copiarAlPortapapeles(texto) { try { await navigator.clipboard.writeText(texto); return true; } catch { // Fallback para navegadores más antiguos const el = document.createElement('textarea'); el.value = texto; document.body.appendChild(el); el.select(); document.execCommand('copy'); document.body.removeChild(el); return true; } }