Arresta tutte le richieste Ajax attive in jQuery


216

Ho un problema, quando si invia un modulo tutte le richieste ajax attive non riescono e ciò provoca un evento di errore.

Come fermare tutte le richieste Ajax attive in jQuery senza trigerrare un errore?

Risposte:


273

Ogni volta che crei una richiesta Ajax puoi utilizzare una variabile per memorizzarla:

var request = $.ajax({
    type: 'POST',
    url: 'someurl',
    success: function(result){}
});

Quindi è possibile interrompere la richiesta:

request.abort();

È possibile utilizzare un array per tenere traccia di tutte le richieste Ajax in sospeso e, se necessario, annullarle.


Grazie, ho aggiunto un FLAG perché ho usato più richieste contemporaneamente
jcho360

ecco un semplice esempio funzionante: stackoverflow.com/a/42312101/3818394
Dharmesh patel

ho una chiamata Ajax in funzione come posso annullarla?
Kalariya_M,

La variabile deve essere dichiarata globale per accedervi da un'altra funzione quando è in corso una chiamata ajax. esempio: un processo di caricamento di più file.
Clain Dsilva,

180

Il frammento seguente consente di mantenere un elenco ( pool ) di richieste e di interromperle tutte se necessario. È meglio posizionarlo nel <HEAD>tuo html, prima di effettuare qualsiasi altra chiamata 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>

2
@mkmurray - su initalization in IE8 mi sembra di ottenere Object doesn't support property or method 'indexOf'? Ho il sospetto che potrebbe essere stackoverflow.com/a/2608601/181971 o magari passare a stackoverflow.com/a/2608618/181971 ?
Tim

3
@grr ha ragione, vedi la sua risposta e controlla i documenti per ajaxSetup .
kzfabi,

@Tim - come suggerito Steven, invece di var index = $ .xhrPool.indexOf (jqXHR); utilizzare: var index = $ .inArray (jqXHR, $ .xhrPool);
Christopher

1
@mkmurray: mostra TypeError: jqXHR.abort non è una funzione per me. :(
Shesha,

C'è un leggero errore logico nel metodo abortAll, che è stato risolto qui in questa risposta stackoverflow.com/a/45500874/1041341
Sarin JS

122

L'uso di ajaxSetup non è corretto , come indicato nella sua pagina doc. Configura solo le impostazioni predefinite e se alcune richieste le sovrascrivono, ci sarà un casino.

Sono in ritardo alla festa, ma solo per riferimento futuro se qualcuno sta cercando una soluzione allo stesso problema, ecco il mio tentativo, ispirato e ampiamente identico alle risposte precedenti, ma più 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);

Come si chiama il metodo abort () da altre funzioni?
Stan James,

abort è una funzione, non un metodo. lo chiami normalmente dallo stesso incapsulamento, se devi usarlo al di fuori dell'incapsulamento puoi rimuovere "var" prima del nome della funzione e diventerà una funzione disponibile a livello globale
Trey

Ciao, qualcuno potrebbe spiegare quando r sarà indefinito?
Varun,

36

Ecco cosa sto usando attualmente per farlo.

$.xhrPool = [];
$.xhrPool.abortAll = function() {
  _.each(this, function(jqXHR) {
    jqXHR.abort();
  });
};
$.ajaxSetup({
  beforeSend: function(jqXHR) {
    $.xhrPool.push(jqXHR);
  }
});

Nota: _.each di underscore.js è presente, ma ovviamente non è necessario. Sono solo pigro e non voglio cambiarlo in $ .each (). 8P


2
Ho una soluzione leggermente modificata che funziona alla grande e che sto per pubblicare.
mkmurray,

7
Questo perde memoria. aboutAlldovrebbe rimuovere gli elementi dall'array. Inoltre, quando una richiesta è terminata, dovrebbe rimuoversi dall'elenco.
Behrang Saeedzadeh,

5
@BehrangSaeedzadeh Avresti dovuto pubblicare anche una versione migliorata.
mattsven,

19

Assegna a ogni richiesta xhr un ID univoco e archivia il riferimento all'oggetto in un oggetto prima di inviarlo. Elimina il riferimento dopo il completamento di una richiesta xhr.

Per annullare tutte le richieste in qualsiasi momento:

$.ajaxQ.abortAll();

Restituisce gli ID univoci della richiesta annullata. Solo a scopo di test.

Funzione di lavoro:

$.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;
    }
  };

})();

Restituisce un oggetto con una singola funzione che può essere utilizzato per aggiungere più funzionalità quando richiesto.


17

L'ho trovato troppo facile per più richieste.

step1: definire una variabile nella parte superiore della pagina:

  xhrPool = []; // no need to use **var**

step2: set beforeInvia in tutte le richieste Ajax:

  $.ajax({
   ...
   beforeSend: function (jqXHR, settings) {
        xhrPool.push(jqXHR);
    },
    ...

step3: utilizzalo ovunque tu abbia richiesto:

   $.each(xhrPool, function(idx, jqXHR) {
          jqXHR.abort();
    });

Ciò perde memoria, proprio come fa stackoverflow.com/a/6618288/1772379 , e proprio per gli stessi motivi.
Ben Johnson,

Modo davvero orribile per scrivere JavaScript.
Ozil,

1
potrebbe essere alla fine è possibile cancellare / svuotare l'array xhrPool
space earth il

6

Ho esteso mkmurray e SpYk3HH in modo che XhrPool.abortAll possa interrompere tutte le richieste in sospeso di un determinato URL :

$.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;
});

L'utilizzo è lo stesso, tranne che abortAll ora può facoltativamente accettare un URL come parametro e annulla solo le chiamate in sospeso a quell'URL


5

Ho avuto dei problemi con il codice di Andy, ma mi ha dato delle idee fantastiche. Il primo problema era che dovremmo eliminare tutti gli oggetti jqXHR completati correttamente. Ho anche dovuto modificare la funzione abortAll. Ecco il mio codice di lavoro finale:

$.xhrPool = [];
$.xhrPool.abortAll = function() {
            $(this).each(function(idx, jqXHR) {
                        jqXHR.abort();
                        });
};
$.ajaxSetup({
    beforeSend: function(jqXHR) {
            $.xhrPool.push(jqXHR);
            }
});
$(document).ajaxComplete(function() {
            $.xhrPool.pop();
            });

Non mi piaceva il modo ajaxComplete () di fare le cose. Non importa come ho provato a configurare .ajaxSetup non ha funzionato.


7
Penso che potresti chiamare pop sulla richiesta sbagliata se non vengono completati in un ordine particolare?
jjmontes,

1
Sì, vuoi fare slice anziché pop. Ho una soluzione leggermente modificata che sto per pubblicare.
mkmurray,

4

Ho aggiornato il codice per farlo funzionare per me

$.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);
        }
    }
});

4

Aggiungendo il mio cappello. Offre metodi aborte removemetodi contro l' xhrPoolarray e non è soggetto a problemi con le ajaxSetupsostituzioni.

/**
 * 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);
});

2

Crea un pool di tutte le richieste Ajax e interrompili .....

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++]);
    }
};

1

Meglio usare un codice indipendente .....

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++]);
    }
};

0

Altrettanto importante: dire che si desidera disconnettersi e si stanno generando nuove richieste con timer: perché i dati della sessione vengono rinnovati con ogni nuovo bootstrap (forse si può dire che sto parlando di Drupal, ma questo potrebbe essere qualsiasi sito che utilizza sessioni). Ho dovuto esaminare tutti i miei script con una ricerca e sostituzione, perché avevo un sacco di cose in esecuzione in diversi casi: variabili globali in alto:

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');
}

0
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));

ogni volta che si desidera interrompere tutta la richiesta Ajax, è sufficiente chiamare questa linea

Request.AbortAll()

-2

C'è una soluzione fittizia che la uso per interrompere tutte le richieste Ajax. Questa soluzione è ricaricare l'intera pagina. Questa soluzione è utile se non ti piace assegnare un ID a ciascuna richiesta Ajax e se fai richieste Ajax all'interno di for-loop. Questo assicurerà che tutte le richieste Ajax vengano eliminate.

location.reload();

-3

Ecco come collegarlo a qualsiasi clic (utile se la tua pagina sta effettuando molte chiamate AJAX e stai provando a navigare via).

$ ->
    $.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()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.