Cancelación de peticiones y AbortController
AbortController es una interfaz del navegador que permite cancelar peticiones Fetch antes de que se completen, mediante una señal AbortSignal. Es ideal cuando necesitas cancelar peticiones por timeout, navegación, cierre de sesión, búsqueda dinámica, etc.
Estructura básica
Para hacer uso de la cancelación de peticiones se debe:
- Crear una instancia de
AbortController. - Acceder a la propiedad
signalde la instancia y compartirla dentro de las opciones de la petición fetch. - En cualquier momento se puede cancelar la petición mediante el controlador.
const controller = new AbortController();
const signal = controller.signal;
fetch('/api/data', { signal })
.then(res => res.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Petición cancelada');
} else {
console.error('Otro error:', error);
}
});
// En algún momento:
controller.abort(); // Esto cancela la petición
También podemos aplicar el concepto dentro de async/await:
async function fetchWithCancel(url: string, controller: AbortController) {
try {
const response = await fetch(url, { signal: controller.signal });
if (!response.ok) throw new Error('Error HTTP');
return await response.json();
} catch (err) {
if ((err as Error).name === 'AbortError') {
console.warn('La petición fue abortada');
} else {
throw err;
}
}
}
Ejemplo: Búsqueda en tiempo real
Definimos una función uqe realizará una búsqueda usando los valores ingresados por el usuario:
let currentController: AbortController | null = null;
async function search(query: string) {
if (currentController) {
currentController.abort(); // Cancela búsqueda anterior
}
currentController = new AbortController();
try {
const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`, {
signal: currentController.signal,
});
const results = await res.json();
console.log('Resultados:', results);
} catch (err) {
if ((err as Error).name === 'AbortError') {
console.log('Búsqueda anterior cancelada');
} else {
console.error('Error en búsqueda:', err);
}
}
}
Cada que el usuario ingresa un valor en el input, la función es llamada y cancela la petición anterior si se encuentra activa, y lanza una nueva petición.
const input = document.querySelector('#busqueda') as HTMLInputElement;
input.addEventListener('input', () => {
const query = input.value.trim();
if (query.length > 2) {
search(query);
}
});
Uso de AbortController para cancelar una petición fetch
- El usuario ejecuta una acción en la plataforma.
- La app recibe el llamado, crea una instancia de AbortController, y obtiene el signal.
- A su vez, la app ejecuta un fetch a la URL y le comparte como propiedad el signal creado.
- La FetchAPI envía una petición HTTP al servidor con la solicitud del usuario.
- El usuario cambia de acción o abandona la vista en la que se encuentra.
- El cambio es detectado por la app y llama a
.abort()para detener la petición. - La instancia de AbortController dispara el evento de cancelación.
- La FetchAPI lanza una excepción por cancelación de la petición.
- La excepción es atrapada en el bloque
try/catch. - La app toma la decisión de mostrar un error al usuario, o de manejarlo internamente y continuar con la ejecución de la aplicación.
Integración avanzada
-
Usando timeout manual:
function fetchWithTimeout(url: string, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
return fetch(url, { signal: controller.signal })
.finally(() => clearTimeout(timeoutId));
} -
Con componentes de UI, por ejemplo en Angular:
ngOnDestroy(): void {
this.controller.abort(); // Evita memory leaks si el usuario abandona el componente
}
Buenas prácticas
| Práctica | Recomendado | Evitar |
|---|---|---|
Usar AbortController para búsquedas dinámicas, navegación, cierre de sesión | ✅ | |
Revisar siempre el nombre del error (AbortError) | ✅ | |
Llamar .abort() sin necesidad real | ❌ | |
| Usar múltiples controladores para múltiples peticiones independientes | ✅ | |
Compartir controller.signal entre distintas peticiones si no deben cancelarse juntas | ❌ |
Referencias
- Mozilla Developer Network. (s.f.). AbortController.
- Mozilla Developer Network. (s.f.). Fetch API.
- Flanagan, D. (2020). JavaScript: The Definitive Guide (7th ed.). O’Reilly Media.
- Google. (s.f.). JavaScript Style Guide.
- TypeScript Handbook. (s.f.). Working with APIs.