Brechen Sie Ajax-Anforderungen mit jQuery ab


1827

Wie kann ich mit jQuery eine Ajax-Anfrage abbrechen / abbrechen , von der ich die Antwort noch nicht erhalten habe?


2
Vielleicht habe ich die Frage falsch verstanden, aber können Sie sie nicht einfach verwenden $.ajaxStop?
Luke Madhanga

17
@LukeMadhanga; Ich denke ajaxStop, erkennt nur, wenn alle AJAX-Anfragen abgeschlossen sind, es stoppt keine Anfrage. Nach meiner Erfahrung würden Sie es so verwenden : $(document).ajaxStop(function(){alert("All done")}). Verwenden .abort()ist die beste Option.
TheCarver

Antworten:


1744

Die meisten jQuery Ajax-Methoden geben ein XMLHttpRequest-Objekt (oder ein gleichwertiges Objekt) zurück, sodass Sie es einfach verwenden können abort().

Siehe die Dokumentation:

  • Abbruchmethode ( MSDN ). Bricht die aktuelle HTTP-Anforderung ab.
  • abort () ( MDN ). Wenn die Anfrage bereits gesendet wurde, bricht diese Methode die Anfrage ab.
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()

UPDATE: Ab jQuery 1.5 ist das zurückgegebene Objekt ein Wrapper für das native XMLHttpRequest-Objekt mit dem Namen jqXHR. Dieses Objekt scheint alle nativen Eigenschaften und Methoden verfügbar zu machen, sodass das obige Beispiel weiterhin funktioniert. Siehe Das jqXHR-Objekt (jQuery-API-Dokumentation).

UPDATE 2: Ab jQuery 3 gibt die Ajax-Methode jetzt ein Versprechen mit zusätzlichen Methoden (wie Abbruch) zurück, sodass der obige Code weiterhin funktioniert, obwohl das zurückgegebene Objekt kein Objekt xhrmehr ist. Siehe den 3.0-Blog hier .

UPDATE 3 : xhr.abort()funktioniert immer noch mit jQuery 3.x. Gehen Sie nicht davon aus, dass das Update 2 korrekt ist. Weitere Informationen zum jQuery Github-Repository .


12
Es ist wie das Klicken auf die Schaltfläche "Stopp" in Ihrem Browser. Die Anfrage wird abgebrochen. Sie können dann dasselbe XHR-Objekt für eine andere Anforderung wiederverwenden.
Meouw

65
@brad Schließt leider abortkeine bestehende Verbindung zum Server, successwird also weiterhin aufgerufen. Dies ist sehr problematisch für Implementierungen von Comet mit langen Abfragen.
pepkin88

6
@ErvWalter Sie können eine weitere Anfrage senden, die die vorherige abbricht.
Asad Saeeduddin

8
In meinen Tests wird die Anforderung im Browser abgebrochen, aber die .fail () -Methode wird mit jqXHR, status = 0, und jqXHR, statusMessage = "abort"
BJ Safdie,

9
.abort()funktioniert immer noch für mich in jQuery 3.2.1. Dieser Kommentar in einem verwandten Github-Problem eines jQuery-Kernteammitglieds scheint zu implizieren, dass diese Antwort falsch ist und .abort() nicht entfernt wurde.
Alarive

117

Sie können die Anforderung nicht zurückrufen, aber Sie können einen Zeitüberschreitungswert festlegen, nach dem die Antwort ignoriert wird. Auf dieser Seite finden Sie die AJAX-Optionen für jquery. Ich glaube, dass Ihr Fehlerrückruf aufgerufen wird, wenn die Zeitüberschreitung überschritten wird. Bei jeder AJAX-Anforderung gibt es bereits ein Standardzeitlimit.

Sie können auch die abort () -Methode für das Anforderungsobjekt verwenden. Der Client hört zwar nicht mehr auf das Ereignis, verhindert jedoch möglicherweise nicht, dass der Server es verarbeitet.


74

Es ist eine asynchrone Anfrage, dh sobald sie gesendet wurde, ist sie da draußen.

Wenn Ihr Server aufgrund der AJAX-Anforderung einen sehr teuren Vorgang startet, können Sie Ihren Server am besten öffnen, um auf Abbruchanforderungen zu warten, und eine separate AJAX-Anforderung senden, in der der Server benachrichtigt wird, dass er seine Aktivitäten beenden soll.

Andernfalls ignorieren Sie einfach die AJAX-Antwort.


48
In diesem Zusammenhang bedeutet asynchron einfach, dass die Anforderung den Skriptfluss nicht unterbricht. Browser haben jetzt die Möglichkeit, die Anforderung vorzeitig abzubrechen, bevor die Anforderung abgeschlossen ist.
ElephantHunter

4
Wie können wir eine Abbruchanforderung an den Server senden? Ich verstehe nicht, woher der Server weiß, welche Anforderung die Verarbeitung beenden soll. Könnten Sie ein Beispiel geben? Vielen Dank.
Lucky Soni

3
@LuckySoni, Elephanthunter diskutiert nur clientseitig. Der Server wird nicht von einer .abort Anfrage betroffen sein
Kloar

4
@Kloar: Wenn die Anforderung noch nicht vom Server empfangen wurde (z. B. große mehrteilige Anforderungen), schließt der Client möglicherweise den Socket und der Server ist betroffen.
Weiß

4
PHP prüft automatisch auf abgebrochene Anfragen und wird ebenfalls automatisch beendet. siehe php.net/manual/en/function.ignore-user-abort.php
hanshenrik

68

Speichern Sie die von Ihnen getätigten Aufrufe in einem Array und rufen Sie dann jeweils xhr.abort () auf.

RIESIGE CAVEAT: Sie können eine Anfrage abbrechen, aber das ist nur die Client-Seite. Die Serverseite könnte die Anforderung weiterhin verarbeiten. Wenn Sie PHP oder ASP mit Sitzungsdaten verwenden, werden die Sitzungsdaten gesperrt, bis der Ajax beendet ist. Damit der Benutzer weiterhin auf der Website surfen kann, müssen Sie session_write_close () aufrufen . Dadurch wird die Sitzung gespeichert und entsperrt, sodass andere Seiten, die auf die Fortsetzung warten, fortgesetzt werden. Ohne dies können mehrere Seiten darauf warten, dass die Sperre entfernt wird.


Da Sie den vorherigen immer stornieren, können Sie das nicht einfach immer tun? (und keine Notwendigkeit, ein Array zu verwenden)
Unpolarität

60

AJAX-Anforderungen werden möglicherweise nicht in der Reihenfolge ausgeführt, in der sie gestartet wurden. Anstatt abzubrechen, können Sie alle AJAX-Antworten außer der neuesten ignorieren :

  • Erstellen Sie einen Zähler
  • Erhöhen Sie den Zähler, wenn Sie eine AJAX-Anforderung initiieren
  • Verwenden Sie den aktuellen Wert des Zählers, um die Anforderung zu "stempeln"
  • Vergleichen Sie im Erfolgsrückruf den Stempel mit dem Zähler, um zu überprüfen, ob es sich um die letzte Anforderung handelt

Grobe Darstellung des Codes:

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 auf jsFiddle


Aufgrund der Einschränkungen beim Abbrechen einer XHR-Anforderung (siehe andere Kommentare auf dieser Seite) ist dies wahrscheinlich die beste und einfachste Option.
Quinn Comendant

41

Wir mussten dieses Problem nur umgehen und drei verschiedene Ansätze testen.

  1. bricht die Anfrage ab, wie von @meouw vorgeschlagen
  2. Führen Sie alle Anforderungen aus, verarbeiten Sie jedoch nur das Ergebnis der letzten Übermittlung
  3. verhindert neue Anfragen, solange noch eine ansteht

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" />

In unserem Fall haben wir uns für Ansatz 3 entschieden, da der Server weniger belastet wird. Ich bin mir jedoch nicht 100% sicher, ob jQuery den Aufruf der .complete () - Methode garantiert. Dies könnte zu einer Deadlock-Situation führen. In unseren Tests konnten wir eine solche Situation nicht reproduzieren.


36

Es ist immer die beste Vorgehensweise, so etwas zu tun.

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

Es ist jedoch viel besser, wenn Sie eine if-Anweisung überprüfen, um zu überprüfen, ob die Ajax-Anforderung null ist oder nicht.


2
Ich überprüfe auch, ob eine Anforderung bereits ausgeführt wird, verwende jedoch einen Booleschen Wert, da dieser leichter ist.
Bitte klicken Sie hier

15

Rufen Sie einfach xhr an. abort () ob es sich um ein jquery ajax-Objekt oder ein natives XMLHTTPRequest-Objekt handelt.

Beispiel:

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

13

Ich habe eine Live-Suchlösung durchgeführt und musste ausstehende Anfragen abbrechen, die möglicherweise länger gedauert haben als die letzte / aktuellste Anfrage.

In meinem Fall habe ich so etwas verwendet:

//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 

12

Wie viele Personen im Thread festgestellt haben, verarbeitet der Server die Anforderung weiterhin, nur weil die Anforderung auf der Clientseite abgebrochen wird. Dies führt zu einer unnötigen Belastung des Servers, da die Arbeit erledigt wird, die wir im Front-End nicht mehr hören.

Das Problem, das ich zu lösen versuchte (auf das möglicherweise auch andere stoßen), besteht darin, dass ich, als der Benutzer Informationen in ein Eingabefeld eingab, eine Anfrage nach einem Google Instant-Gefühl auslösen wollte.

Um unnötige Anfragen zu vermeiden und die Schnelligkeit des Frontends aufrechtzuerhalten, habe ich Folgendes getan:

var xhrQueue = [];
var xhrCount = 0;

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

    xhrQueue.push(xhrCount);

    setTimeout(function(){

        xhrCount = ++xhrCount;

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

    }, 150);

});

Dadurch wird im Wesentlichen alle 150 ms eine Anfrage gesendet (eine Variable, die Sie an Ihre eigenen Bedürfnisse anpassen können). Wenn Sie Probleme haben, zu verstehen , was genau hier passiert, meldet xhrCountund xhrQueuean die Konsole kurz vor dem if - Block.


11

Verwenden Sie einfach ajax.abort (), um beispielsweise eine ausstehende Ajax-Anfrage abzubrechen, bevor Sie eine solche senden

//check for existing ajax request
if(ajax){ 
 ajax.abort();
 }
//then you make another ajax request
$.ajax(
 //your code here
  );

11

Sie können damit jeden kontinuierlichen Ajax-Anruf abbrechen

<input id="searchbox" name="searchbox" type="text" />

<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>

<script type="text/javascript">
     var request = null;
        $('#searchbox').keyup(function () {
            var id = $(this).val();
            request = $.ajax({
                type: "POST", //TODO: Must be changed to POST
                url: "index.php",
                data: {'id':id},
                success: function () {

                },
                beforeSend: function () {
                    if (request !== null) {
                        request.abort();
                    }
                }
            });
        });

</script>

10

Es gibt keinen zuverlässigen Weg, dies zu tun, und ich würde es nicht einmal versuchen, sobald die Anfrage unterwegs ist. Die einzige Möglichkeit, vernünftig zu reagieren, besteht darin , die Antwort zu ignorieren .

In den meisten Fällen kann dies in folgenden Situationen vorkommen: Ein Benutzer klickt zu oft auf eine Schaltfläche, die viele aufeinanderfolgende XHR auslöst. Hier haben Sie viele Optionen. Blockieren Sie entweder die Schaltfläche, bis XHR zurückgegeben wird, oder lösen Sie nicht einmal eine neue XHR aus, während ein anderer Hinweis ausführt Der Benutzer muss sich zurücklehnen - oder alle ausstehenden XHR-Antworten außer den letzten verwerfen.


7

Der folgende Code zeigt das Initiieren und Abbrechen einer Ajax-Anforderung:

function libAjax(){
  var req;
  function start(){

  req =    $.ajax({
              url: '1.php',
              success: function(data){
                console.log(data)
              }
            });

  }

  function stop(){
    req.abort();
  }

  return {start:start,stop:stop}
}

var obj = libAjax();

 $(".go").click(function(){


  obj.start();


 })



 $(".stop").click(function(){

  obj.stop();


 })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" class="go" value="GO!" >
   <input type="button" class="stop" value="STOP!" >

5
Bitte erläutern Sie, wie dies die Frage löst. Dies wird dem OP und anderen zukünftigen Suchenden helfen.
SnareChops

5

Ich hatte das Problem des Abrufs und sobald die Seite geschlossen wurde, wurde die Abfrage fortgesetzt, sodass ein Benutzer in meinem Fall ein Update verpassen würde, da ein MySQL-Wert für die nächsten 50 Sekunden nach dem Schließen der Seite festgelegt wurde, obwohl ich die Ajax-Anforderung beendet habe Wenn Sie $ _SESSION verwenden, um eine Variable festzulegen, wird sie in der Umfrage nicht selbst aktualisiert, bis sie beendet ist und eine neue gestartet wurde. Ich habe also in meiner Datenbank einen Wert als 0 = offpage festgelegt, während ich bin Abfrage Ich frage diese Zeile ab und gebe false zurück. Wenn es 0 ist, erhalten Sie beim Abfragen beim Abrufen offensichtlich aktuelle Werte ...

Ich hoffe das hat geholfen


5

Wenn xhr.abort(); das Neuladen der Seite verursacht wird,

Dann können Sie onreadystatechangevor dem Abbruch einstellen , um Folgendes zu verhindern:

// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();

4

Ich habe eine Demo freigegeben , die zeigt, wie eine AJAX-Anforderung abgebrochen wird, wenn Daten nicht innerhalb einer vordefinierten Wartezeit vom Server zurückgegeben werden.

HTML:

<div id="info"></div>

JS CODE:

var isDataReceived= false, waitTime= 1000; 
$(function() {
    // Ajax request sent.
     var xhr= $.ajax({
      url: 'http://api.joind.in/v2.1/talks/10889',
      data: {
         format: 'json'
      },     
      dataType: 'jsonp',
      success: function(data) {      
        isDataReceived= true;
        $('#info').text(data.talks[0].talk_title);        
      },
      type: 'GET'
   });
   // Cancel ajax request if data is not loaded within 1sec.
   setTimeout(function(){
     if(!isDataReceived)
     xhr.abort();     
   },waitTime);   
});

1
$.ajaxbietet eine timeoutOption, sodass Sie keine eigenen schreiben müssen. Einfach benutzen ..., data: {...}, timeout: waitTime,....
Bram Vanroy
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.