javascript abort - Bricht Ajax-Anfragen mit jQuery ab





close on (16)


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

  1. storniert die Anfrage wie von @meouw vorgeschlagen
  2. Führe alle Anfragen aus, verarbeitet aber nur das Ergebnis der letzten Übermittlung
  3. verhindert neue Anfragen, solange noch eine aussteht

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 den Ansatz Nr. 3 entschieden, da der Server weniger belastet wird. Aber ich bin nicht 100% sicher, wenn jQuery den Aufruf der .complete () - Methode garantiert, könnte dies zu einer Deadlock-Situation führen. In unseren Tests konnten wir eine solche Situation nicht reproduzieren.

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




Es ist eine asynchrone Anfrage, was bedeutet, sobald es gesendet wird, ist es da draußen.

Falls Ihr Server aufgrund der AJAX-Anfrage einen sehr teuren Vorgang startet, sollten Sie Ihren Server so öffnen, dass er auf Löschanforderungen wartet, und eine separate AJAX-Anfrage senden, die den Server benachrichtigt, damit er stoppt, was auch immer er tut.

Andernfalls ignorieren Sie einfach die AJAX-Antwort.




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

Aber es ist viel besser, wenn Sie eine if-Anweisung überprüfen, um zu überprüfen, ob die Ajax-Anfrage null ist oder nicht.




Sie können die Anforderung nicht abrufen, aber Sie können einen Zeitüberschreitungswert festlegen, nach dem die Antwort ignoriert wird. Siehe diese page für jquery AJAX Optionen. Ich glaube, dass Ihr Fehler Callback aufgerufen wird, wenn die Zeitüberschreitung überschritten wird. Für jede AJAX-Anfrage gibt es bereits eine Standard-Zeitüberschreitung.

Sie können auch die abort() -Methode für das Anforderungsobjekt verwenden. Dies führt zwar dazu, dass der Client nicht mehr auf das Ereignis wartet, der Server kann ihn jedoch möglicherweise nicht mehr verarbeiten.




es gibt keinen zuverlässigen Weg, es 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 es passieren, dass ein Benutzer zu oft auf eine Schaltfläche klickt, die viele aufeinanderfolgende XHRs auslöst. Hier haben Sie viele Möglichkeiten: entweder die Schaltfläche sperren, bis XHR zurückgegeben wird, oder gar kein neues XHR auslösen, während ein anderer Hinting ausführt der Benutzer, um sich zurückzulehnen - oder verwerfen alle ausstehenden XHR-Antwort, aber die jüngsten.




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

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

Grober Umriss 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




Die meisten jQuery Ajax-Methoden geben ein XMLHttpRequest-Objekt (oder das entsprechende Objekt) zurück, sodass Sie abort() .

Siehe die Dokumentation:

  • Abbruchmethode ( MSDN ). Bricht die aktuelle HTTP-Anfrage 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 systemeigenen Eigenschaften und Methoden verfügbar zu machen, so dass das obige Beispiel immer noch funktioniert. Siehe das jqXHR-Objekt (jQuery-API-Dokumentation).

UPDATE 2: Ab jQuery 3 gibt die Ajax-Methode ein Versprechen ohne zusätzliche Methoden (wie Abbruch) zurück, so dass dies nicht mehr funktioniert. Sehen Sie den 3.0 Blog hier . Eine Möglichkeit besteht darin, das xhr-Objekt über die Eigenschaft xhr zu steuern. Hier ist ein grobes Beispiel:

var xhr = new window.XMLHttpRequest();
var request = $.ajax({
    url : url,
    xhr : function(){
        return xhr;
    }
});
xhr.abort();



Ich habe eine demo , die zeigt, wie man eine AJAX-Anfrage abbricht - 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);   
});



Ruf einfach xhr an. abort () ob es ein jquery ajax Objekt oder ein natives XMLHTTPRequest Objekt ist.

Beispiel:

//jQuery ajax
$(document).ready(
    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);






Wie viele Leute im Thread bemerkt haben, wird der Server die Anfrage immer noch verarbeiten, nur weil die Anfrage auf der Client-Seite abgebrochen wird. Dies erzeugt eine unnötige Belastung für den Server, da es Arbeiten ausführt, auf die wir im Front-End nicht mehr hören.

Das Problem, das ich zu lösen versuchte (das andere auch dazu führen können), besteht darin, dass ich, wenn 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 das Snappiness des Frontends beizubehalten, 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);

});

Dies sendet im Wesentlichen alle 150ms eine Anfrage (eine Variable, die Sie für Ihre eigenen Bedürfnisse anpassen können). Wenn Sie nicht genau xhrQueue , was genau hier passiert, loggen Sie xhrCount und xhrQueue vor dem if-Block in die Konsole ein.




Verwenden Sie einfach ajax.abort () zum Beispiel, um eine ausstehende Ajax-Anfrage abzubrechen, bevor Sie eine andere wie diese senden

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



Speichern Sie die Anrufe, die Sie in einem Array tätigen, und rufen Sie dann je xhr.abort () auf.

RIESIGE HÖHE: Sie können eine Anfrage abbrechen, aber das ist nur die Client-Seite. Die Serverseite könnte die Anfrage noch bearbeiten. Wenn Sie etwas wie PHP oder ASP mit Sitzungsdaten verwenden, sind die Sitzungsdaten gesperrt, bis der Ajax beendet ist. Damit der Benutzer die Website weiter durchsuchen kann, müssen Sie session_write_close () aufrufen. Dies speichert die Sitzung und entsperrt sie, so dass andere Seiten, die darauf warten, fortzufahren, fortfahren werden. Andernfalls können mehrere Seiten darauf warten, dass das Schloss entfernt wird.




Ich hatte das Problem des Pollings und sobald die Seite geschlossen wurde, ging die Umfrage weiter. In meinem Fall würde ein Benutzer ein Update verpassen, da ein Mysql-Wert für die nächsten 50 Sekunden nach Schließen der Seite gesetzt wurde, obwohl ich die Ajax-Anfrage, I, beendete Um es herum zu finden, benutze $ _SESSION, um eine Variable zu setzen, wird nicht in der Abfrage selbst aktualisiert, bis sie beendet ist und eine neue begonnen hat. Also habe ich einen Wert in meiner Datenbank als 0 = offpage gesetzt, während ich bin polling Ich frage diese Zeile ab und gebe false zurück; Wenn es 0 ist, wenn Sie in der Abfrage abfragen, erhalten Sie offensichtlich aktuelle Werte ...

Ich hoffe, das hat geholfen




Wenn xhr.abort(); bewirkt, dass die Seite neu geladen wird,

Dann können Sie onreadystatechange vor dem Abbruch setzen, um onreadystatechange zu verhindern:

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



Verwenden Sie die Klassenumschaltung, nicht die Stilbearbeitung. . .

Die Verwendung von Klassen zum "Ausblenden" von Elementen ist einfach und auch eine der effizientesten Methoden. Das Umschalten einer Klasse "verborgen" mit einem Display "Keine" führt zu einer schnelleren Bearbeitung als die direkte Bearbeitung dieses Stils. Ich habe einiges davon in der -Frage ausführlich erklärt. Drehen von zwei Elementen im selben Div sichtbar / verborgen .

JavaScript Best Practices und Optimierung

Hier ist ein wirklich aufschlussreiches Video eines Google Tech Talk von Nicholas Zakas, dem Front-End-Ingenieur von Google:





javascript jquery ajax