Fetch: cancelar solicitudes
Aprende a cancelar solicitudes fetch en JavaScript con AbortController y AbortSignal: cancelaciones manuales, tiempos de espera, cancelar múltiples solicitudes y manejar AbortError correctamente.
Una vez que una solicitud fetch() está en curso, continúa ejecutándose hasta que el servidor responde — incluso si el usuario ha navegado a otra página, ha escrito un nuevo término de búsqueda, o la respuesta ya no es necesaria. Esas solicitudes desperdiciadas ocupan conexiones, consumen batería y ancho de banda, y pueden entregar resultados obsoletos que sobreescriben los más recientes. La interfaz AbortController te ofrece una forma limpia y estándar de cancelar una solicitud bajo demanda.
Este capítulo muestra cómo conectar AbortController, reaccionar a las acciones del usuario, crear tiempos de espera, cancelar varias solicitudes a la vez y manejar el AbortError resultante correctamente. Para obtener más información sobre fetch en sí, consulta la página anterior, Fetch API.
Cómo funciona AbortController
AbortController es un objeto pequeño con una sola función: posee un AbortSignal y puede cambiar ese signal al estado abortado. El signal es la parte que se le pasa a fetch() (y a muchas otras API del navegador, como addEventListener). Cuando llamas a controller.abort(), todas las operaciones que recibieron ese signal se cancelan.
El patrón siempre sigue los mismos tres pasos:
- Crear un controlador:
const controller = new AbortController(). - Pasar
controller.signalafetch()en el objeto de opciones. - Llamar a
controller.abort()cuando quieras cancelar.
Cuando se cancela un fetch, su promesa rechaza con un DOMException cuyo name es "AbortError". Por eso cada ejemplo a continuación comprueba error.name === 'AbortError' — para poder ignorar la cancelación deliberada y aun así mostrar los errores de red reales.
Uso básico de AbortController
Aquí está el ejemplo completo más pequeño posible. Cancela inmediatamente para que puedas ver el camino de rechazo:
Creamos un AbortController, pasamos su signal a fetch() y llamamos inmediatamente a controller.abort(). Como la solicitud nunca se completa normalmente, se ejecuta el .catch() e informa la cancelación.
Inspeccionando el signal: aborted y el evento abort
El signal expone su estado para que otro código pueda reaccionar a una cancelación. Dos miembros son los más importantes:
signal.aborted— un boolean que se vuelvetrueuna vez cancelado.- el evento
"abort"— se dispara en el signal en el momento en que se llama aabort().
Esto es útil cuando tienes trabajo no relacionado con fetch (un temporizador, una animación, un lector de stream) que debería detenerse en el momento en que se cancela la solicitud.
Un controlador, un uso. Un controlador no puede reiniciarse. Una vez que llamas a
abort(), ese signal permanece en estado abortado para siempre, y cualquier nuevofetch()que inicies con él rechaza instantáneamente. Para una nueva solicitud, crea un nuevoAbortController.
Ejemplo práctico: cancelar ante una acción del usuario
La razón más común para cancelar es que el usuario cambia de opinión — hace clic en "Cancelar", cierra un diálogo, o escribe una nueva consulta antes de que la anterior haya terminado. Aquí un botón cancela una solicitud en curso:
<body>
<button id="abortButton">Abort Fetch Request</button>
<script>
const controller = new AbortController();
const signal = controller.signal;
document.getElementById('abortButton').addEventListener('click', () => {
controller.abort();
});
fetch('https://httpbin.org/delay/5', { signal })
.then(response => response.json())
.then(data => alert(
'Data is successfully fetched! Refresh the page and try aborting.'
))
.catch(error => {
if (error.name === 'AbortError') {
alert('Fetch request was aborted by the user');
} else {
alert('Fetch error: ' + error.message);
}
});
</script>
</body>Al hacer clic en el botón con el ID abortButton se cancela la solicitud fetch en curso. El endpoint https://httpbin.org/delay/5 tarda deliberadamente 5 segundos, así que si haces clic dentro de ese tiempo la solicitud rechaza con AbortError.
Cancelar varias solicitudes a la vez
Un único signal puede pasarse a muchas solicitudes. Una sola llamada a controller.abort() las cancela todas — útil cuando una página abandona una vista que inició varias cargas en paralelo:
Como las tres solicitudes comparten un mismo signal, controller.abort() las cancela en una sola llamada y Promise.all rechaza con AbortError. Para aprender más sobre cómo ejecutar solicitudes en paralelo, consulta Promise API.
Cancelar tras un tiempo de espera
Un uso muy común de AbortController es darle a una solicitud un límite de tiempo: si el servidor es demasiado lento, cancela y muestra un error en lugar de esperar indefinidamente.
El método manual con setTimeout
Puedes combinar el controlador con un temporizador e integrarlo con cualquier otra lógica asíncrona. Aquí una operación separada activa la cancelación después de un segundo, mientras que el endpoint tardaría cinco:
El fetch se cancela por el temporizador tras un segundo, mucho antes de que el endpoint de cinco segundos pueda responder. Lee más sobre temporizadores en async/await.
El atajo: AbortSignal.timeout()
Los navegadores modernos (y Node 17.3+) incluyen un helper integrado que crea un signal que se cancela solo después de un número determinado de milisegundos — sin necesidad de controlador ni setTimeout:
Ten en cuenta que una cancelación por tiempo de espera rechaza con un TimeoutError, no con un AbortError, por lo que puedes distinguir "tardó demasiado" de "el usuario canceló". Si necesitas ambas cosas — un tiempo de espera y un botón de cancelación manual — combina los signals con AbortSignal.any([userSignal, AbortSignal.timeout(2000)]).
Manejar AbortError correctamente
Cada vez que cancelas un fetch, la promesa rechaza. Olvidar manejarlo produce un ruidoso "uncaught promise rejection" en la consola, aunque la cancelación haya sido intencional. Dos reglas mantienen todo limpio:
- Siempre incluye un
.catch()(otry/catchconawait) en un fetch cancelable. - Dentro de él, comprueba
error.namey trata'AbortError'/'TimeoutError'como esperados — solo registra o muestra los otros errores. Consulta Manejo de errores con promesas para el patrón más amplio.
Conclusión
AbortController es la forma estándar de cancelar solicitudes fetch() en JavaScript. Crea un controlador, pasa su signal a una o más solicitudes y llama a abort() cuando el trabajo ya no sea necesario. Has visto la cancelación activada por el usuario, los tiempos de espera manuales e integrados, la cancelación de múltiples solicitudes a la vez y cómo manejar el AbortError resultante. Aplicar estos patrones mantiene tus aplicaciones responsivas y evita que desperdicien tiempo en resultados que nadie está esperando.