Icono del sitio BorrowBits

Truco: Abortar peticiones AJAX pendientes antes de enviar otra

En algunas ocasiones interesa cancelar o detener varias peticiones AJAX que ya han sido realizadas. En un sistema muy asíncrono, puede que unas llamadas sean más prioritarias que otras o que incluso cierta petición deba anular al resto de peticiones pendientes….

Existe un método del viejo XMLHttpRequest llamado abort() que realiza esta función y que también está soportado por jQuery. La idea es ejecutarlo justo antes de enviar al servidor una petición AJAX prioritaria que deba anular a las que ya estuvieran activas.

Pero, ¿cómo anularlas todas de un plumazo?

El truco consiste en «apilar» cada conexión justo antes de realizar una llamada y «desapilarla» al completar la petición. Una función abortarAll() se encargaría de cancelarlas todas a la vez. He aquí el código:


$.xhrPool = [];
$.xhrPool.abortAll = function() {
$(this).each(function(idx, jqXHR) {
jqXHR.abort();
});
$.xhrPool.length = 0
};
 $.ajaxSetup({
beforeSend: function(jqXHR) {
$.xhrPool.push(jqXHR);
},
complete: function(jqXHR) {
var index = $.xhrPool.indexOf(jqXHR);
if (index > -1) {
$.xhrPool.splice(index, 1);
}
}
});

La función de jQuery .ajaxSetup() establece una configuración por defecto común a todas las llamadas .ajax() que se realicen en el futuro (incluso para aquellas que se llevan a cabo a través de la función .load()).

Precaución: como .ajaxSetup() establece una configuración por defecto hemos de tener cuidado de no sobrescribir sus parámetros más adelante. La documentación oficial desaconseja su uso por esta misma razón.

Ahora imaginaos que nos toca ejecutar una llamada asíncrona prioritaria que debe cancelar al resto. Llamamos a la función así:

$.xhrPool.abortAll();

//Llamada con prioridad
.ajax(…);

Una última aclaración

Cuando una petición ha sido enviada al servidor, esta queda fuera de nuestro control. Lo que hace .abort() es ignorar cualquier respuesta que pudiera devolver el servidor a partir del momento en que ha sido abortada, pero la petición podría haber sido procesada en el servidor.

Salir de la versión móvil