Fetch avanzado: cancelar, reintentar y evitar carreras
Aprende a construir peticiones HTTP resistentes con AbortController, timeouts, retry con backoff y protección contra respuestas fuera de orden en interfaces dinámicas.
En producción, las peticiones no siempre responden rápido ni bien: hay timeouts, cortes intermitentes y respuestas antiguas que llegan tarde.
Un flujo robusto de fetch necesita tres pilares: cancelar solicitudes obsoletas, reintentar fallos temporales y validar estados HTTP explícitamente.
Sin estos patrones, la UI puede mostrar datos inconsistentes o generar doble carga innecesaria al backend.
Objetivo de esta lección: diseñar capa de red resiliente y predecible usando abort, retry y control de concurrencia.
- Fetch no termina en await: debes pensar en fallos reales de infraestructura.
- `fetch` solo rechaza en errores de red; respuestas 404/500 no lanzan por sí mismas. Por eso debes comprobar `response.ok` antes de parsear.
- Además, en interfaces con búsquedas o filtros rápidos, necesitas cancelar solicitudes previas para evitar que una respuesta antigua pise la nueva.
- Si la respuesta tarda demasiado, cancelas de forma explícita.
- Combinar `AbortController` con `setTimeout` permite imponer un límite de espera y liberar la UI cuando la red está degradada.
Mentalidad de resiliencia en red
Fetch no termina en await: debes pensar en fallos reales de infraestructura.
`fetch` solo rechaza en errores de red; respuestas 404/500 no lanzan por sí mismas. Por eso debes comprobar `response.ok` antes de parsear.
Además, en interfaces con búsquedas o filtros rápidos, necesitas cancelar solicitudes previas para evitar que una respuesta antigua pise la nueva.
AbortController y timeout manual
Si la respuesta tarda demasiado, cancelas de forma explícita.
Combinar `AbortController` con `setTimeout` permite imponer un límite de espera y liberar la UI cuando la red está degradada.
Recuerda limpiar el timer en `finally` para evitar fugas y comportamientos inesperados.
- Abortar no significa error fatal: puede ser decisión de UX.
- Diferencia AbortError de otros errores en tu capa de UI.
- Evita timeouts excesivos que bloqueen feedback al usuario.
- Centraliza helper para usar política consistente en toda la app.
Retry con backoff para fallos temporales
No reintentes todo sin criterio: define cuándo y cuántas veces.
Un retry lineal/agresivo puede amplificar carga del sistema. Mejor aplica backoff exponencial corto y límite de intentos.
Reintenta solo en errores potencialmente recuperables (timeouts, 429, 503), no en validaciones funcionales.
Evitar race conditions en búsquedas y filtros
La respuesta más lenta no debe sobrescribir la más reciente.
En inputs de búsqueda, cada tecla puede lanzar un fetch nuevo. Si no abortas el anterior, una respuesta vieja podría pintar resultados incorrectos.
La combinación de `AbortController` + token/contador de request te da control fino sobre qué respuesta es válida.
- Aborta request anterior cuando cambie el criterio de búsqueda.
- Ignora AbortError en UI para no mostrar falso error al usuario.
- Muestra estado de loading ligado a la petición vigente.
- Evita múltiples fuentes de verdad para resultados.
Checklist de fetch robusto en producción
Con este protocolo, tu capa de red será más confiable y mantenible.
El valor de estos patrones aparece cuando hay mala red, backend inestable o uso intenso de la interfaz.
Revisar cancelación, reintentos y estados HTTP antes de desplegar evita gran parte de bugs intermitentes difíciles de reproducir.
- Validación explícita de `response.ok`.
- AbortController para timeout y cancelación de obsoletos.
- Retry acotado con backoff y criterio de idempotencia.
- Mensajes de UX claros diferenciando cancelado, temporal y fallo definitivo.