Domanda Abort Ajax richiede l'uso di jQuery


Usando jQuery, come posso annulla / annulla una richiesta Ajax da cui non ho ancora ricevuto risposta?


1632
2018-01-15 12:45


origine


risposte:


La maggior parte dei metodi jQuery Ajax restituisce un oggetto XMLHttpRequest (o equivalente), quindi puoi semplicemente usarlo abort().

Vedi la documentazione:

  • metodo abortire (MSDN). Annulla la richiesta HTTP corrente.
  • abort () (MDN). Se la richiesta è già stata inviata, questo metodo interromperà la richiesta.
var xhr = $.ajax({
    type: "POST",
    url: "some.php",
    data: "name=John&location=Boston",
    success: function(msg){
       alert( "Data Saved: " + msg );
    }
});

//kill the request
xhr.abort()

AGGIORNARE: A partire da jQuery 1.5 l'oggetto restituito è un wrapper per l'oggetto XMLHttpRequest nativo chiamato jqXHR. Questo oggetto sembra esporre tutte le proprietà e i metodi nativi, quindi l'esempio precedente funziona ancora. Vedere L'oggetto jqXHR (documentazione dell'API jQuery).

AGGIORNAMENTO 2: A partire da jQuery 3, il metodo ajax ora restituisce una promessa con metodi aggiuntivi (come abort), quindi il codice sopra riportato funziona ancora, sebbene l'oggetto che viene restituito non sia un xhr più. Vedere il 3.0 blog qui.

AGGIORNAMENTO 3: xhr.abort() funziona ancora su jQuery 3.x. Non dare per scontato il aggiornamento 2 è corretta. Maggiori informazioni sul repository Greeub di jQuery.


1591
2018-01-15 12:56



Non è possibile richiamare la richiesta ma è possibile impostare un valore di timeout dopo il quale la risposta verrà ignorata. Guarda questo pagina per le opzioni jQuery AJAX. Credo che il tuo callback di errore verrà chiamato se il periodo di timeout viene superato. Esiste già un timeout predefinito per ogni richiesta AJAX.

Puoi anche usare il abort () metodo sull'oggetto richiesta ma, mentre causerà al client di interrompere l'ascolto dell'evento, esso potrebbe probabilmente non impedirà al server di elaborarlo.


106
2018-01-15 12:55



È un asincrono richiesta, nel senso che una volta inviata è là fuori.

Nel caso in cui il server stia iniziando un'operazione molto costosa a causa della richiesta AJAX, il meglio che puoi fare è aprire il tuo server per ascoltare le richieste di annullamento e inviare una richiesta AJAX separata per notificare al server di interrompere qualunque cosa stia facendo.

Altrimenti, semplicemente ignora la risposta AJAX.


70
2018-01-15 12:56



Salva le chiamate che fai in un array, quindi chiama xhr.abort () su ognuna.

HAVE CAVEAT: puoi annullare una richiesta, ma è solo il lato client. Il lato server potrebbe ancora elaborare la richiesta. Se stai usando qualcosa come PHP o ASP con i dati di sessione, i dati della sessione sono bloccati fino a quando l'ajax non è terminato. Quindi, per consentire all'utente di continuare a navigare nel sito Web, è necessario chiamare session_write_close(). Ciò salva la sessione e la sblocca in modo che le altre pagine in attesa di continuare procedano. Senza questo, diverse pagine possono essere in attesa di rimozione del blocco.


62
2018-03-28 11:34



Le richieste AJAX potrebbero non essere completate nell'ordine in cui sono state avviate. Invece di interrompere, puoi scegliere di ignorare tutte le risposte AJAX tranne quella più recente:

  • Crea un contatore
  • Incrementa il contatore quando avvii una richiesta AJAX
  • Utilizzare il valore corrente del contatore per "timbrare" la richiesta
  • Nella callback di successo confrontare il timbro con il contatore per verificare se era la richiesta più recente

Profilo approssimativo del codice:

var xhrCount = 0;
function sendXHR() {
    // sequence number for the current invocation of function
    var seqNumber = ++xhrCount;
    $.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {
        // this works because of the way closures work
        if (seqNumber === xhrCount) {
            console.log("Process the response");
        } else {
            console.log("Ignore the response");
        }
    });
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last 
// one will trigger "Process the response" message

Demo su jsFiddle


45
2018-01-18 12:55



Abbiamo solo dovuto risolvere questo problema e testato tre diversi approcci.

  1. annulla la richiesta come suggerito da @meouw
  2. esegue tutte le richieste ma elabora solo il risultato dell'ultima sottomissione
  3. impedisce nuove richieste fino a quando un altro è ancora in sospeso

var Ajax1 = {
  call: function() {
    if (typeof this.xhr !== 'undefined')
      this.xhr.abort();
    this.xhr = $.ajax({
      url: 'your/long/running/request/path',
      type: 'GET',
      success: function(data) {
        //process response
      }
    });
  }
};
var Ajax2 = {
  counter: 0,
  call: function() {
    var self = this,
      seq = ++this.counter;
    $.ajax({
      url: 'your/long/running/request/path',
      type: 'GET',
      success: function(data) {
        if (seq === self.counter) {
          //process response
        }
      }
    });
  }
};
var Ajax3 = {
  active: false,
  call: function() {
    if (this.active === false) {
      this.active = true;
      var self = this;
      $.ajax({
        url: 'your/long/running/request/path',
        type: 'GET',
        success: function(data) {
          //process response
        },
        complete: function() {
          self.active = false;
        }
      });
    }
  }
};
$(function() {
  $('#button').click(function(e) {
    Ajax3.call();
  });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="button" type="button" value="click" />

Nel nostro caso abbiamo deciso di utilizzare l'approccio n. 3 in quanto produce meno carico per il server. Ma non sono sicuro al 100% se jQuery garantisce la chiamata del metodo .complete () -, questo potrebbe produrre una situazione di deadlock. Nei nostri test non siamo riusciti a riprodurre una situazione del genere.


36
2018-03-06 14:29



È sempre consigliabile fare qualcosa del genere.

var $request;
if ($request != null){ 
    $request.abort();
    $request = null;
}

$request = $.ajax({
    type : "POST", //TODO: Must be changed to POST
    url : "yourfile.php",
    data : "data"
    }).done(function(msg) {
        alert(msg);
    });

Ma è molto meglio se si controlla una dichiarazione if per verificare se la richiesta Ajax è nullo o no.


30
2017-10-15 09:14



la soluzione di meouw è corretto, ma se sei interessato a un maggiore controllo, puoi provare a Plugin Ajax Manager per jQuery.


19
2018-01-15 15:45



Stavo facendo una soluzione di ricerca in tempo reale e avevo bisogno di cancellare le richieste in sospeso che potrebbero aver richiesto più tempo della richiesta più recente / più recente.

Nel mio caso ho usato qualcosa del genere:

//On document ready
var ajax_inprocess = false;

$(document).ajaxStart(function() {
ajax_inprocess = true;
});

$(document).ajaxStop(function() {
ajax_inprocess = false;
});

//Snippet from live search function
if (ajax_inprocess == true)
{
    request.abort();
}
//Call for new request 

11
2017-12-04 14:43



Come molte persone sul thread hanno notato, solo perché la richiesta è stata interrotta sul lato client, il server continuerà a elaborare la richiesta. Questo crea un carico non necessario sul server perché sta facendo del lavoro che abbiamo smesso di ascoltare sul front-end.

Il problema che stavo tentando di risolvere (che altri potrebbero eseguire anche in) è che quando l'utente immetteva informazioni in un campo di input, volevo attivare una richiesta per un tipo di sensazione di Google Instant.

Per evitare di lanciare richieste non necessarie e mantenere la reattività del front-end, ho fatto quanto segue:

var xhrQueue = [];
var xhrCount = 0;

$('#search_q').keyup(function(){

    xhrQueue.push(xhrCount);

    setTimeout(function(){

        xhrCount = ++xhrCount;

        if (xhrCount === xhrQueue.length) {
            // Fire Your XHR //
        }

    }, 150);

});

In pratica invierà una richiesta ogni 150 ms (una variabile che è possibile personalizzare in base alle proprie esigenze). Se hai problemi a capire cosa sta succedendo esattamente qui, registrati xhrCount e xhrQueue alla console appena prima del blocco if.


10
2018-02-03 18:43



Basta chiamare xhr.abort () se si tratta di oggetti jquery ajax o nativi XMLHTTPRequest.

esempio:

//jQuery ajax
$(document).ready(function(){
    var xhr = $.get('/server');
    setTimeout(function(){xhr.abort();}, 2000);
});

//native XMLHTTPRequest
var xhr = new XMLHttpRequest();
xhr.open('GET','/server',true);
xhr.send();
setTimeout(function(){xhr.abort();}, 2000);

9
2018-05-28 09:17