JQuery AJAX isteği nasıl iptal edilir / iptal edilir?


244

Her 5 saniyede bir yapılacak AJAX isteğim var. Ancak sorun, önceki istek tamamlanmadıysa AJAX isteğinden önce bu isteği iptal edip yeni bir istekte bulunmam gerekiyor.

Kodum böyle bir şey, bu sorunu nasıl çözebilirim?

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

    var interval = setInterval(fn, 500);
);


5
Sorunuz, isteğin her 5 saniyede bir gerçekleşmesi gerektiğini belirtiyor, ancak kod 500 ms = 0,5 sn kullanıyor.
geon

Yanıtlar:


355

Jquery ajax yöntemi bir XMLHttpRequest nesnesi döndürür . İsteği iptal etmek için bu nesneyi kullanabilirsiniz.

XMLHttpRequest, isteği iptal eden bir iptal yöntemine sahiptir , ancak istek sunucuya zaten gönderildiyse , isteği iptal etsek bile istemci isteği işleyecektir, ancak istemci yanıtı beklemeyecek / işlemeyecektir.

Xhr nesnesi ayrıca isteğin durumunu içeren bir readyState içerir (UNSENT-0, OPENED-1, HEADERS_RECEIVED-2, LOADING-3 ve DONE-4). önceki isteğin yerine getirilip getirilmediğini kontrol etmek için bunu kullanabiliriz.

$(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);
);

60
@romkyns Farklılıklar readystateyukarıdaki ve readyStateaşağıdaki özelliklerdir s, karakter jQuery 1.5'te büyük harfle yazılmıştır
Arun P Johny

ReadyState "LOADING-3" ise ve iptal edersek ne olacağını merak ediyordum? Veriler sunucuya gönderilir ve işlenir veya işlenmez.
Bilmeyeceğiz

7
Ancak, readyState kontrolünün gereksiz olduğunu düşünüyorum, çünkü ertelendi ve çözüldükten veya reddedildikten sonra diğerlerini çalıştırmayacak. Yani if (xhr) xhr.abort();çok iyi çalışır.
Kasım'da Ciantic

2
W3 hiç kullanılmamış readystate, belgelerinde büyük harf kullanılmamıştır . Her zaman büyük harfle yazılmıştır readyStateve jquery (1.5'ten önce veya sonra) w3 belirtimiyle doğru bir şekilde eşleşir.
Arashsoft

@ArunPJohny, bu soruyu pls yapabilir misiniz stackoverflow.com/questions/49801146/…
Krishna Jonnalagadda

6

Bir sunucuya istekte bulunduğunuzda, önce bir ilerlemenin boş olup olmadığını (veya bu verileri getirip getirmediğini) kontrol etmesini isteyin. Veri getiriliyorsa, önceki isteği iptal edin ve yeni isteği başlatın.

var progress = null

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

5

Bu biraz geç olabilir biliyorum ama ben iptal yöntemi çağıran gerçekten isteği iptal etmedi nerede benzer sorunlar yaşıyorum. bunun yerine tarayıcı hala hiç kullanmadığı bir yanıt bekliyordu. bu kod bu sorunu çözdü.

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

1

Neden isteği iptal etmelisiniz?

Her istek beş saniyeden fazla sürerse ne olur?

İstekle birlikte geçen parametre değişmiyorsa isteği iptal etmemelisiniz. örneğin: - talep bildirim verilerinin alınması içindir. Bu gibi durumlarda, hoş yaklaşım, yalnızca önceki Ajax isteğini tamamladıktan sonra yeni bir istek ayarlanmasıdır.

$(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);

);

5
Bu kötü bir fikir. Yeni bir çağrı başlatırken, etkinliğin tamamının önceki çağrıdan başlatılmasını istemezsiniz. Bu yaklaşımla çok garip sonuçlar elde edebilirsiniz.
Webberig

1

Jquery-validate.js kullanabilirsiniz. Aşağıda jquery-validate.js kod pasajı bulunmaktadır.

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

Yani sadece tek parametre ayarlamak gerektiğini modu için iptal Eğer ajax isteği yapan zaman.

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


0

jQuery: Bunu başlangıç ​​noktası olarak kullanın - ilham kaynağı olarak. Bu şekilde çözdüm: (bu mükemmel bir çözüm değil, sadece son örneği iptal ediyor ve WIP kodu)

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.

0

API'nızı aramak için bir işlev oluşturun. Bu işlev içinde isteği tanımlarız callApiRequest = $.get(...- bu bir değişkenin tanımı olmasına rağmen, istek hemen çağrılır, ancak şimdi istek değişken olarak tanımlanmıştır. İstek çağrılmadan önce değişkenimizin tanımlanıp tanımlanmadığını typeof(callApiRequest) != 'undefined've beklemede olup olmadığını kontrol ederiz suggestCategoryRequest.state() == 'pending'- her ikisi de doğruysa, .abort()başarılı geri aramanın çalışmasını önleyecek olan isteği biz yaparız .

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

    });
}

Sunucunuz / API'nız isteği iptal etmeyi desteklemeyebilir (API zaten bir kod çalıştırdıysa?), Ancak javascript geri çağrısı tetiklenmez. Bu, örneğin hashtag girişi gibi bir kullanıcıya giriş önerileri sunarken kullanışlıdır.

Hata geri arama tanımı ekleyerek bu işlevi daha da genişletebilirsiniz; istek iptal edilirse ne olur?

Bu snippet'in ortak kullanım durumu, keypressolayı başlatan bir metin girişi olacaktır . İptal etmeniz gereken (bazı) isteklerin gönderilmesini önlemek için bir zaman aşımı kullanabilirsiniz .abort().


-7

Ayrıca readyState 0'ı da kontrol etmelisiniz. Çünkü xhr.abort () işlevini kullandığınızda bu işlev bu nesnede readyState değerini 0 olarak ayarlar ve if denetiminiz her zaman true olur - 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);
); 

2
Arun'un cevabını kopyalayıp yapıştırdınız mı? Çünkü böyle iki kod blokları tam olarak aynı, boşluk ve tüm olma olasılığı ...

@ user2700923 Yazısı tam olarak aynı değil. Amacı, readyState 0'ı da kontrol etmemiz gerektiğidir. Ancak bu, Arun'un cevabına bir yorum olarak daha uygun olurdu.
Stefan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.