Wie kann ich eine jQuery AJAX-Anfrage abbrechen / abbrechen?

244

Ich habe eine AJAX-Anfrage, die alle 5 Sekunden gestellt wird. Das Problem liegt jedoch vor der AJAX-Anforderung, wenn die vorherige Anforderung nicht abgeschlossen ist. Ich muss diese Anforderung abbrechen und eine neue Anforderung stellen.

Mein Code ist ungefähr so. Wie kann ich dieses Problem beheben?

$(document).ready(
    var fn = function(){
        $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);
user556673
quelle
10
Mögliches Duplikat von Kill Ajax-Anfragen mit Javascript mit JQuery.
Karim79
5
Ihre Frage besagt, dass die Anforderung alle 5 Sekunden erfolgen soll, der Code jedoch 500 ms = 0,5 s verwendet.
Geon

Antworten:

355

Die jquery ajax-Methode gibt ein XMLHttpRequest- Objekt zurück. Mit diesem Objekt können Sie die Anforderung abbrechen.

Die XMLHttpRequest verfügt über eine Abbruchmethode , die die Anforderung abbricht. Wenn die Anforderung jedoch bereits an den Server gesendet wurde, verarbeitet der Server die Anforderung auch dann, wenn die Anforderung abgebrochen wird, der Client jedoch nicht auf die Antwort wartet / diese verarbeitet.

Das xhr-Objekt enthält auch einen readyState, der den Status der Anforderung enthält (UNSENT-0, OPENED-1, HEADERS_RECEIVED-2, LOADING-3 und DONE-4). Damit können wir überprüfen, ob die vorherige Anfrage abgeschlossen wurde.

$(document).ready(
    var xhr;

    var fn = function(){
        if(xhr && xhr.readyState != 4){
            xhr.abort();
        }
        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);
Arun P Johny
quelle
60
@romkyns Die Unterschiede sind die Eigenschaft readystateoben und readyStateunten, der Charakter swird in jQuery 1.5
Arun P Johny
Ich habe mich gefragt, was passiert, wenn der readyState "LOADING-3" ist und wir abbrechen? Die Daten werden an den Server gesendet und verarbeitet oder nicht. Wir werden es nicht wissen ...: S
inf3rno
7
Übrigens denke ich, dass die readyState-Prüfung nicht erforderlich ist, da sie zurückgestellt wird und die anderen nicht ausgeführt werden, sobald sie gelöst oder abgelehnt wurde. Also if (xhr) xhr.abort();wird auch gut funktionieren.
Ciantic
2
W3 wurde readystatein seiner Dokumentation nie verwendet und nicht groß geschrieben . Es wurde immer groß geschrieben readyStateund die Abfrage (vor oder nach 1.5) entspricht korrekt der w3-Spezifikation.
Arashsoft
@ArunPJohny, können Sie diese Frage stellen stackoverflow.com/questions/49801146/…
Krishna Jonnalagadda
5

Ich weiß, dass dies etwas spät sein könnte, aber ich habe ähnliche Probleme, bei denen das Aufrufen der Abbruchmethode die Anforderung nicht wirklich abgebrochen hat. Stattdessen wartete der Browser immer noch auf eine Antwort, die er nie verwendet. Dieser Code hat dieses Problem behoben.

 try {
        xhr.onreadystatechange = null;
        xhr.abort();
} catch (e) {}
Lyon
quelle
5

Wenn Sie eine Anfrage an einen Server stellen, lassen Sie ihn zuerst überprüfen, ob ein Fortschritt nicht null ist (oder diese Daten abruft). Wenn Daten abgerufen werden, brechen Sie die vorherige Anforderung ab und initiieren Sie die neue.

var progress = null

function fn () {    
    if (progress) {
        progress.abort();
    }
    progress = $.ajax('ajax/progress.ftl', {
        success: function(data) {
            //do something
            progress = null;
        }
    });
}
Taz
quelle
1

Warum sollten Sie die Anfrage abbrechen?

Was passiert, wenn jede Anfrage länger als fünf Sekunden dauert?

Sie sollten die Anforderung nicht abbrechen, wenn sich der mit der Anforderung übergebene Parameter nicht ändert. Beispiel: - Die Anforderung dient zum Abrufen der Benachrichtigungsdaten. In solchen Situationen besteht der nette Ansatz darin, eine neue Anforderung erst nach Abschluss der vorherigen Ajax-Anforderung festzulegen.

$(document).ready(

    var fn = function(){

        $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            },

            complete: function(){setTimeout(fn, 500);}
        });
    };

     var interval = setTimeout(fn, 500);

);
Habeeb Perwad
quelle
5
Das ist eine schlechte Idee. Wenn Sie einen neuen Anruf starten, möchten Sie nicht, dass das gesamte Ereignis des vorherigen Anrufs ausgelöst wird. Mit diesem Ansatz können sehr seltsame Ergebnisse erzielt werden.
Webberig
1

Sie können jquery-validate.js verwenden. Das Folgende ist das Code-Snippet aus jquery-validate.js.

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()

var pendingRequests = {},
    ajax;
// Use a prefilter if available (1.5+)
if ( $.ajaxPrefilter ) {
    $.ajaxPrefilter(function( settings, _, xhr ) {
        var port = settings.port;
        if ( settings.mode === "abort" ) {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            pendingRequests[port] = xhr;
        }
    });
} else {
    // Proxy ajax
    ajax = $.ajax;
    $.ajax = function( settings ) {
        var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
            port = ( "port" in settings ? settings : $.ajaxSettings ).port;
        if ( mode === "abort" ) {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            pendingRequests[port] = ajax.apply(this, arguments);
            return pendingRequests[port];
        }
        return ajax.apply(this, arguments);
    };
}

Damit Sie einfach nur den Parameter einstellen müssen Modus abbrechen , wenn Sie Ajax - Anfrage machen.

Ref: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js

zawhtut
quelle
0

jQuery: Verwenden Sie dies als Ausgangspunkt - als Inspiration. Ich habe es so gelöst: (Dies ist keine perfekte Lösung, es bricht nur die letzte Instanz ab und ist WIP-Code)

var singleAjax = function singleAjax_constructor(url, params) {
    // remember last jQuery's get request
    if (this.lastInstance) {
        this.lastInstance.abort();  // triggers .always() and .fail()
        this.lastInstance = false;
    }

    // how to use Deferred : http://api.jquery.com/category/deferred-object/
    var $def = new $.Deferred();

    // pass the deferrer's request handlers into the get response handlers
    this.lastInstance = $.get(url, params)
        .fail($def.reject)         // triggers .always() and .fail()
        .success($def.resolve);    // triggers .always() and .done()

    // return the deferrer's "control object", the promise object
    return $def.promise();
}


// initiate first call
singleAjax('/ajax.php', {a: 1, b: 2})
    .always(function(a,b,c) {console && console.log(a,b,c);});

// second call kills first one
singleAjax('/ajax.php', {a: 1, b: 2})
    .always(function(a,b,c) {console && console.log(a,b,c);});
    // here you might use .always() .fail() .success() etc.
BananaAcid
quelle
0

Erstellen Sie eine Funktion zum Aufrufen Ihrer API. Innerhalb dieser Funktion definieren wir die Anforderung callApiRequest = $.get(...- obwohl dies eine Definition einer Variablen ist, wird die Anforderung sofort aufgerufen, aber jetzt haben wir die Anforderung als Variable definiert. Bevor die Anforderung aufgerufen wird, prüfen wir, ob unsere Variable definiert ist typeof(callApiRequest) != 'undefined'und ob sie aussteht. suggestCategoryRequest.state() == 'pending'Wenn beide wahr sind, wird .abort()die Anforderung, die den erfolgreichen Rückruf verhindert, ausgeführt.

// We need to wrap the call in a function
callApi = function () {

    //check if request is defined, and status pending
    if (typeof(callApiRequest) != 'undefined'
        && suggestCategoryRequest.state() == 'pending') {

        //abort request
        callApiRequest.abort()

    }

    //define and make request
    callApiRequest = $.get("https://example.com", function (data) {

        data = JSON.parse(data); //optional (for JSON data format)
        //success callback

    });
}

Ihr Server / Ihre API unterstützt möglicherweise nicht das Abbrechen der Anforderung (was ist, wenn die API bereits Code ausgeführt hat?), Der Javascript-Rückruf wird jedoch nicht ausgelöst. Dies ist nützlich, wenn Sie beispielsweise einem Benutzer Eingabevorschläge bereitstellen, z. B. die Eingabe von Hashtags.

Sie können diese Funktion weiter erweitern, indem Sie die Definition des Fehlerrückrufs hinzufügen. Was soll passieren, wenn die Anforderung abgebrochen wurde?

Ein häufiger Anwendungsfall für dieses Snippet ist eine Texteingabe, die bei einem keypressEreignis ausgelöst wird. Sie können eine Zeitüberschreitung verwenden, um das Senden (einiger) Anforderungen zu verhindern, die Sie abbrechen müssen .abort().

mate.gwozdz
quelle
-7

Sie sollten auch nach readyState 0 suchen. Wenn Sie xhr.abort () verwenden, setzt diese Funktion readyState in diesem Objekt auf 0, und Ihre if-Prüfung ist immer wahr - readyState! = 4

$(document).ready(
    var xhr;

    var fn = function(){
        if(xhr && xhr.readyState != 4 && xhr.readyState != 0){
            xhr.abort();
        }
        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
); 
Programmierer
quelle
2
Haben Sie Aruns Antwort kopiert und eingefügt? Weil die Wahrscheinlichkeit, dass zwei
@ user2700923 Sein Beitrag ist nicht genau der gleiche. Sein Punkt ist, dass wir auch nach readyState 0 suchen sollten. Dies wäre jedoch als Kommentar zu Aruns Antwort angemessener gewesen.
Stefan