W3docs

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:

  1. Crear un controlador: const controller = new AbortController().
  2. Pasar controller.signal a fetch() en el objeto de opciones.
  3. 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:

javascript— editable

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 vuelve true una vez cancelado.
  • el evento "abort" — se dispara en el signal en el momento en que se llama a abort().
javascript— editable

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 nuevo fetch() que inicies con él rechaza instantáneamente. Para una nueva solicitud, crea un nuevo AbortController.

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:

javascript— editable

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:

javascript— editable

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:

javascript— editable

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() (o try/catch con await) en un fetch cancelable.
  • Dentro de él, comprueba error.name y 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.

Práctica

Práctica
¿Cuál es el propósito de pasar la propiedad signal de un AbortController a una solicitud fetch?
¿Cuál es el propósito de pasar la propiedad signal de un AbortController a una solicitud fetch?
Was this page helpful?