JavaScript de Cero a Experto / Asincronía II
fetch III: errores, estados de carga y AbortController
Esta lección separa el código de tutorial del código profesional: la
trampa más famosa de fetch (un 404 que NO dispara tu catch), los tres
estados que toda petición debe mostrarle al usuario, y la cancelación con
AbortController — la promesa pendiente del módulo 8, cumplida.
La trampa: el 404 que tu catch nunca ve
Ese helper cargarJSON — fetch + chequeo de ok + throw + json — es de
las funciones más reescritas del planeta: escríbela una vez por proyecto y
todas tus peticiones quedan protegidas. Con ella, tus try/catch atrapan
las DOS familias de fallo: los de red (rechazo natural) y los HTTP (tu
throw).
El trío profesional: cargando, éxito, error
El usuario SIEMPRE merece saber en qué va su petición. El patrón es un
try/catch/finally mapeado al DOM — y aquí se junta todo: módulos 7, 8 y
la asincronía:
Haz las dos rutas: carga completa, y carga cancelada a mitad de camino.
Fíjate en el mapa: try arranca mostrando "cargando" y bloqueando el
botón, el éxito pinta el dato, el catch distingue la cancelación
(error.name === "AbortError") de un fallo real, y el finally
desbloquea SIEMPRE — sin él, un error dejaría el botón muerto para
siempre. Ese es el mismo signal que apagaba listeners en el módulo 8:
un solo mecanismo de cancelación para todo el lenguaje. Y el atajo
moderno para timeouts: fetch(url, { signal: AbortSignal.timeout(5000) })
— "esta petición o 5 segundos, lo que pase primero" sin fabricar
controlador.
Tu app consulta una API y el servidor responde 500 (error interno). Tu catch no se entera y la app pinta 'undefined' como si nada. ¿Por qué?
Mini-reto
Endurece el playground del trío: 1) cambia la URL al usuario 999 y
verifica que tu chequeo de ok convierte el 404 en el estado de error
(con el mensaje HTTP); 2) agrega el timeout moderno —
AbortSignal.timeout(1000) — y baja la demora artificial para que a veces
pase y a veces no; 3) el toque fino: si hay una consulta en vuelo y el
usuario vuelve a hacer clic, cancela la anterior antes de arrancar la
nueva (guarda el controlador y abórtalo al inicio del listener). Ese
detalle es ORO en el reto que viene.
Qué sigue
Tienes el arsenal asíncrono completo: promesas, async/await, combinadores, fetch con todos sus modales. El reto del módulo lo junta todo en una app real: un buscador de países contra una API pública, con estados de carga, errores bien tratados y cancelación de búsquedas viejas. El examen final de la asincronía.