Respuestas:
Cada vez que crea una solicitud ajax, puede usar una variable para almacenarla:
var request = $.ajax({
type: 'POST',
url: 'someurl',
success: function(result){}
});
Entonces puedes abortar la solicitud:
request.abort();
Puede utilizar una matriz que rastrea todas las solicitudes pendientes de ajax y abortarlas si es necesario.
El siguiente fragmento le permite mantener una lista ( grupo ) de solicitudes y cancelarlas todas si es necesario. Lo mejor es colocarlo en <HEAD>
su html, antes de realizar cualquier otra llamada AJAX.
<script type="text/javascript">
$(function() {
$.xhrPool = [];
$.xhrPool.abortAll = function() {
$(this).each(function(i, jqXHR) { // cycle through list of recorded connection
jqXHR.abort(); // aborts connection
$.xhrPool.splice(i, 1); // removes from list by index
});
}
$.ajaxSetup({
beforeSend: function(jqXHR) { $.xhrPool.push(jqXHR); }, // annd connection to list
complete: function(jqXHR) {
var i = $.xhrPool.indexOf(jqXHR); // get index for current connection completed
if (i > -1) $.xhrPool.splice(i, 1); // removes from list by index
}
});
})
</script>
Object doesn't support property or method 'indexOf'
? Sospecho que podría ser stackoverflow.com/a/2608601/181971 o tal vez simplemente cambiar a stackoverflow.com/a/2608618/181971 ?
El uso de ajaxSetup no es correcto , como se señala en su página de documentación. Solo configura los valores predeterminados, y si algunas solicitudes los anulan, habrá un desastre.
Llego tarde a la fiesta, pero solo para referencia futura si alguien está buscando una solución al mismo problema, aquí está mi intento, inspirado y en gran parte idéntico a las respuestas anteriores, pero más completo
// Automatically cancel unfinished ajax requests
// when the user navigates elsewhere.
(function($) {
var xhrPool = [];
$(document).ajaxSend(function(e, jqXHR, options){
xhrPool.push(jqXHR);
});
$(document).ajaxComplete(function(e, jqXHR, options) {
xhrPool = $.grep(xhrPool, function(x){return x!=jqXHR});
});
var abort = function() {
$.each(xhrPool, function(idx, jqXHR) {
jqXHR.abort();
});
};
var oldbeforeunload = window.onbeforeunload;
window.onbeforeunload = function() {
var r = oldbeforeunload ? oldbeforeunload() : undefined;
if (r == undefined) {
// only cancel requests if there is no prompt to stay on the page
// if there is a prompt, it will likely give the requests enough time to finish
abort();
}
return r;
}
})(jQuery);
Esto es lo que estoy usando actualmente para lograr eso.
$.xhrPool = [];
$.xhrPool.abortAll = function() {
_.each(this, function(jqXHR) {
jqXHR.abort();
});
};
$.ajaxSetup({
beforeSend: function(jqXHR) {
$.xhrPool.push(jqXHR);
}
});
Nota: _.each of underscore.js está presente, pero obviamente no es necesario. Solo soy flojo y no quiero cambiarlo a $ .each (). 8P
aboutAll
debería eliminar los elementos de la matriz. Además, cuando finaliza una solicitud, debe eliminarse de la lista.
Dele a cada solicitud xhr una identificación única y almacene la referencia del objeto en un objeto antes de enviarlo. Elimine la referencia después de que se complete una solicitud xhr.
Para cancelar toda solicitud en cualquier momento:
$.ajaxQ.abortAll();
Devuelve los identificadores únicos de la solicitud cancelada. Solo con fines de prueba.
Función de trabajo:
$.ajaxQ = (function(){
var id = 0, Q = {};
$(document).ajaxSend(function(e, jqx){
jqx._id = ++id;
Q[jqx._id] = jqx;
});
$(document).ajaxComplete(function(e, jqx){
delete Q[jqx._id];
});
return {
abortAll: function(){
var r = [];
$.each(Q, function(i, jqx){
r.push(jqx._id);
jqx.abort();
});
return r;
}
};
})();
Devuelve un objeto con una sola función que se puede usar para agregar más funcionalidad cuando sea necesario.
Lo encontré demasiado fácil para múltiples solicitudes.
Paso 1: define una variable en la parte superior de la página:
xhrPool = []; // no need to use **var**
Paso 2: establecer antes de enviar en todas las solicitudes ajax:
$.ajax({
...
beforeSend: function (jqXHR, settings) {
xhrPool.push(jqXHR);
},
...
Paso 3: úsalo donde lo necesites:
$.each(xhrPool, function(idx, jqXHR) {
jqXHR.abort();
});
Extendí mkmurray y la respuesta SpYk3HH anterior para que xhrPool.abortAll pueda abortar todas las solicitudes pendientes de una URL dada :
$.xhrPool = [];
$.xhrPool.abortAll = function(url) {
$(this).each(function(i, jqXHR) { // cycle through list of recorded connection
console.log('xhrPool.abortAll ' + jqXHR.requestURL);
if (!url || url === jqXHR.requestURL) {
jqXHR.abort(); // aborts connection
$.xhrPool.splice(i, 1); // removes from list by index
}
});
};
$.ajaxSetup({
beforeSend: function(jqXHR) {
$.xhrPool.push(jqXHR); // add connection to list
},
complete: function(jqXHR) {
var i = $.xhrPool.indexOf(jqXHR); // get index for current connection completed
if (i > -1) $.xhrPool.splice(i, 1); // removes from list by index
}
});
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
console.log('ajaxPrefilter ' + options.url);
jqXHR.requestURL = options.url;
});
El uso es el mismo, excepto que abortAll ahora puede aceptar opcionalmente una url como parámetro y cancelará solo las llamadas pendientes a esa url
Tuve algunos problemas con el código de Andy, pero me dio algunas ideas geniales. El primer problema fue que deberíamos extraer cualquier objeto jqXHR que se complete con éxito. También tuve que modificar la función abortAll. Aquí está mi código de trabajo final:
$.xhrPool = [];
$.xhrPool.abortAll = function() {
$(this).each(function(idx, jqXHR) {
jqXHR.abort();
});
};
$.ajaxSetup({
beforeSend: function(jqXHR) {
$.xhrPool.push(jqXHR);
}
});
$(document).ajaxComplete(function() {
$.xhrPool.pop();
});
No me gustó la forma de hacer las cosas ajaxComplete (). No importa cómo intenté configurar .ajaxSetup, no funcionó.
He actualizado el código para que funcione para mí.
$.xhrPool = [];
$.xhrPool.abortAll = function() {
$(this).each(function(idx, jqXHR) {
jqXHR.abort();
});
$(this).each(function(idx, jqXHR) {
var index = $.inArray(jqXHR, $.xhrPool);
if (index > -1) {
$.xhrPool.splice(index, 1);
}
});
};
$.ajaxSetup({
beforeSend: function(jqXHR) {
$.xhrPool.push(jqXHR);
},
complete: function(jqXHR) {
var index = $.inArray(jqXHR, $.xhrPool);
if (index > -1) {
$.xhrPool.splice(index, 1);
}
}
});
Lanzando mi sombrero. Ofertas abort
y remove
métodos contra la xhrPool
matriz, y no es propenso a problemas con las ajaxSetup
anulaciones.
/**
* Ajax Request Pool
*
* @author Oliver Nassar <onassar@gmail.com>
* @see http://stackoverflow.com/questions/1802936/stop-all-active-ajax-requests-in-jquery
*/
jQuery.xhrPool = [];
/**
* jQuery.xhrPool.abortAll
*
* Retrieves all the outbound requests from the array (since the array is going
* to be modified as requests are aborted), and then loops over each of them to
* perform the abortion. Doing so will trigger the ajaxComplete event against
* the document, which will remove the request from the pool-array.
*
* @access public
* @return void
*/
jQuery.xhrPool.abortAll = function() {
var requests = [];
for (var index in this) {
if (isFinite(index) === true) {
requests.push(this[index]);
}
}
for (index in requests) {
requests[index].abort();
}
};
/**
* jQuery.xhrPool.remove
*
* Loops over the requests, removes it once (and if) found, and then breaks out
* of the loop (since nothing else to do).
*
* @access public
* @param Object jqXHR
* @return void
*/
jQuery.xhrPool.remove = function(jqXHR) {
for (var index in this) {
if (this[index] === jqXHR) {
jQuery.xhrPool.splice(index, 1);
break;
}
}
};
/**
* Below events are attached to the document rather than defined the ajaxSetup
* to prevent possibly being overridden elsewhere (presumably by accident).
*/
$(document).ajaxSend(function(event, jqXHR, options) {
jQuery.xhrPool.push(jqXHR);
});
$(document).ajaxComplete(function(event, jqXHR, options) {
jQuery.xhrPool.remove(jqXHR);
});
Haga un grupo de todas las solicitudes de ajax y abortarlas .....
var xhrQueue = [];
$(document).ajaxSend(function(event,jqxhr,settings){
xhrQueue.push(jqxhr); //alert(settings.url);
});
$(document).ajaxComplete(function(event,jqxhr,settings){
var i;
if((i=$.inArray(jqxhr,xhrQueue)) > -1){
xhrQueue.splice(i,1); //alert("C:"+settings.url);
}
});
ajaxAbort = function (){ //alert("abortStart");
var i=0;
while(xhrQueue.length){
xhrQueue[i++] .abort(); //alert(i+":"+xhrQueue[i++]);
}
};
Mejor usar código independiente .....
var xhrQueue = [];
$(document).ajaxSend(function(event,jqxhr,settings){
xhrQueue.push(jqxhr); //alert(settings.url);
});
$(document).ajaxComplete(function(event,jqxhr,settings){
var i;
if((i=$.inArray(jqxhr,xhrQueue)) > -1){
xhrQueue.splice(i,1); //alert("C:"+settings.url);
}
});
ajaxAbort = function (){ //alert("abortStart");
var i=0;
while(xhrQueue.length){
xhrQueue[i++] .abort(); //alert(i+":"+xhrQueue[i++]);
}
};
Igual de importante: digamos que desea cerrar sesión y está generando nuevas solicitudes con temporizadores: porque los datos de la sesión se renuevan con cada arranque nuevo (tal vez pueda decir que estoy hablando de Drupal, pero este podría ser cualquier sitio que use sesiones). Tuve que revisar todos mis scripts con una búsqueda y reemplazo, porque tenía un montón de cosas ejecutándose en diferentes casos: variables globales en la parte superior:
var ajReq = [];
var canAj = true;
function abort_all(){
for(x in ajReq){
ajReq[x].abort();
ajReq.splice(x, 1)
}
canAj = false;
}
function rmvReq(ranNum){
var temp = [];
var i = 0;
for(x in ajReq){
if(x == ranNum){
ajReq[x].abort();
ajReq.splice(x, 1);
}
i++;
}
}
function randReqIndx(){
if(!canAj){ return 0; }
return Math.random()*1000;
}
function getReqIndx(){
var ranNum;
if(ajReq.length){
while(!ranNum){
ranNum = randReqIndx();
for(x in ajReq){
if(x===ranNum){
ranNum = null;
}
}
}
return ranMum;
}
return randReqIndx();
}
$(document).ready(function(){
$("a").each(function(){
if($(this).attr('href').indexOf('/logout')!=-1){
$(this).click(function(){
abort_all();
});
}
})
});
// Then in all of my scripts I wrapped my ajax calls... If anyone has a suggestion for a
// global way to do this, please post
var reqIndx = getReqIndx();
if(reqIndx!=0){
ajReq[reqIndx] = $.post(ajax, { 'action': 'update_quantities', iids:iidstr, qtys:qtystr },
function(data){
//..do stuff
rmvReq(reqIndx);
},'json');
}
var Request = {
List: [],
AbortAll: function () {
var _self = this;
$.each(_self.List, (i, v) => {
v.abort();
});
}
}
var settings = {
"url": "http://localhost",
success: function (resp) {
console.log(resp)
}
}
Request.List.push($.ajax(settings));
cada vez que desee cancelar toda la solicitud de ajax, solo necesita llamar a esta línea
Request.AbortAll()
Hay una solución ficticia que la uso para cancelar todas las solicitudes de ajax. Esta solución es volver a cargar toda la página. Esta solución es buena si no le gusta asignar una ID a cada solicitud ajax, y si realiza solicitudes ajax dentro de for-loop. Esto asegurará que se eliminen todas las solicitudes de ajax.
location.reload();
Aquí le mostramos cómo conectar esto con cualquier clic (útil si su página está haciendo muchas llamadas AJAX y está tratando de navegar).
$ ->
$.xhrPool = [];
$(document).ajaxSend (e, jqXHR, options) ->
$.xhrPool.push(jqXHR)
$(document).ajaxComplete (e, jqXHR, options) ->
$.xhrPool = $.grep($.xhrPool, (x) -> return x != jqXHR);
$(document).delegate 'a', 'click', ->
while (request = $.xhrPool.pop())
request.abort()