Uso de async/await para código limpio y consumo de APIs con fetch.
Async/Await
asyncconvierte una función en promesa y permite usarawaitdentro.awaitespera una promesa y devuelve su valor sin necesidad dethen.- Errores: se manejan con
try/catchcomo si fuera código síncrono. - Paralelo vs secuencial: esperar una por una es más lento; usa
Promise.allpara paralelizar. - No bloquea el hilo:
awaitpausa la funcion async, pero el event loop sigue atendiendo otras tareas. - Evitar
awaiten loops: si no depende uno del otro, dispara todo y luegoPromise.all.
javascript1async function cargarTodo() { 2 // Secuencial 3 const user = await fetch("/api/user").then(r => r.json()); 4 const posts = await fetch("/api/posts").then(r => r.json()); 5 6 // Paralelo 7 const [u, p] = await Promise.all([ 8 fetch("/api/user").then(r => r.json()), 9 fetch("/api/posts").then(r => r.json()), 10 ]); 11 12 return { user, posts, u, p }; 13}
javascript1// Evitar await dentro de for cuando se puede paralelizar 2const ids = [1, 2, 3]; 3const promesas = ids.map((id) => fetch(`/api/user/${id}`)); 4const respuestas = await Promise.all(promesas);
Fetch API
- GET para leer datos y POST para crear;
fetchdevuelve una promesa. - Errores HTTP:
fetchno lanza error automático, hay que validarresponse.ok. - Headers y JSON: define
Content-Typey usaJSON.stringify. - Timeouts:
AbortControllerpermite cancelar peticiones lentas. - Parseo:
response.json()tambien devuelve una promesa; se debeawait. - CORS: si el servidor no permite el origen, el navegador bloquea la respuesta.
javascript1async function fetchSeguro(url) { 2 const res = await fetch(url); 3 if (!res.ok) throw new Error(`HTTP ${res.status}`); 4 return res.json(); 5} 6 7async function crearPost(data) { 8 const res = await fetch("/api/posts", { 9 method: "POST", 10 headers: { "Content-Type": "application/json" }, 11 body: JSON.stringify(data), 12 }); 13 if (!res.ok) throw new Error("Error al crear"); 14 return res.json(); 15}
javascript1// Timeout con AbortController 2async function fetchConTimeout(url, ms) { 3 const controller = new AbortController(); 4 const timer = setTimeout(() => controller.abort(), ms); 5 try { 6 const res = await fetch(url, { signal: controller.signal }); 7 if (!res.ok) throw new Error(`HTTP ${res.status}`); 8 return res.json(); 9 } finally { 10 clearTimeout(timer); 11 } 12}
Proyecto completo: Weather App
- Obtener clima por ciudad, mostrar resultados y manejar errores.
- Guardar última búsqueda en localStorage.
- Debe tener estados claros: loading, success, empty, error.
- Agregar debounce al input para no disparar llamadas en cada tecla.
- Manejar ciudades no encontradas con mensaje amigable.
Ejemplos de Código
3 ejemplos
Async simple
1async function esperar(ms) {
2 return new Promise((resolve) => setTimeout(resolve, ms));
3}Fetch seguro
1async function fetchSeguro(url) {
2 const res = await fetch(url);
3 if (!res.ok) throw new Error("Error HTTP");
4 return res.json();
5}Cancelar petición
1const controller = new AbortController();
2setTimeout(() => controller.abort(), 3000);
3fetch("/api", { signal: controller.signal });Recursos
4 recursos disponibles
¡Hora de Practicar!
Práctica guiada - Weather App
Práctica
Implementar un buscador de clima con fetch y async/await.
Desafío de Código
Ejercicios - Fetch y JSON
Ejercicios
(1) Consumir JSONPlaceholder, (2) crear POST con datos de usuario, (3) manejo de errores 404/500, (4) cancelar una peticion con AbortController.
Taller Práctico
Proyecto de la semana
Proyecto
- Descripción: Dashboard de datos con consumo de APIs, filtros, loading states y caché en localStorage.
- Detalle: incluir paginacion basica y una barra de busqueda con debounce.
Reto de Lectura
Reto de Lectura — Traducción bilingüe: .then ↔ async/await
Dos versiones del mismo código asíncrono, cada una con un bug distinto y sutil. Tradúcelas en ambos sentidos y encuentra qué rompe cada una.
Un desarrollador debe dominar ambos dialectos: leer cadenas de .then (código existente) y escribir async/await (código nuevo). Cada versión de abajo tiene un bug distinto.
Versión A (.then) — encuentra por qué mostrarTitulos imprime undefined:
javascript1function cargarTitulos() { 2 return fetch("https://jsonplaceholder.typicode.com/posts?userId=1") 3 .then((res) => res.json()) 4 .then((posts) => { 5 posts.map((p) => p.title); 6 }) 7 .catch((err) => console.error("Error:", err)); 8} 9 10function mostrarTitulos() { 11 cargarTitulos().then((titulos) => { 12 console.log(titulos); // undefined 🚨 13 }); 14}
Versión B (async/await) — encuentra qué error NUNCA será atrapado:
javascript1async function cargarYProcesar() { 2 try { 3 const res = await fetch("https://jsonplaceholder.typicode.com/users"); 4 const usuarios = await res.json(); 5 return usuarios; 6 } catch (err) { 7 console.error("Error de red:", err); 8 return []; 9 } 10} 11 12function iniciar() { 13 const usuarios = cargarYProcesar(); 14 console.log("Total:", usuarios.length); // 🚨 imprime undefined... ¿por qué? 15 usuarios.forEach((u) => console.log(u.name)); // 🚨 y esto truena 16}
Tareas:
- Explica el bug de cada versión (son diferentes entre sí).
- Traduce la versión A corregida a async/await.
- Traduce la versión B corregida a .then.
- ¿Cuál de los dos bugs crees que es más común en código generado por IA y por qué es difícil de detectar leyendo?