JQuery'deki tüm etkin ajax isteklerini durdurma


216

Bir form gönderirken tüm etkin ajax isteği başarısız olur ve bu hata olayı tetikler bir sorun var.

Trigerring hata olayı olmadan jQuery'deki tüm etkin ajax istekleri nasıl durdurulur?

Yanıtlar:


273

Her bir ajax isteği oluşturduğunuzda, bunu saklamak için bir değişken kullanabilirsiniz:

var request = $.ajax({
    type: 'POST',
    url: 'someurl',
    success: function(result){}
});

Ardından isteği iptal edebilirsiniz:

request.abort();

Bekleyen tüm ajax isteklerini takip eden bir dizi kullanabilir ve gerekirse iptal edebilirsiniz.


THXs, bir FLAG ekledim çünkü aynı anda birden fazla istek kullandım
jcho360

İşte basit çalışma örneği: stackoverflow.com/a/42312101/3818394
Dharmesh patel

i fonksiyonu nasıl iptal edebilirim ajax çağrı var?
Kalariya_M

Bir ajax çağrısı devam ederken değişkenin başka bir işlevden erişebilmesi için global olarak bildirilmesi gerekir. örnek: çoklu dosya yükleme işlemi.
Clain Dsilva

180

Aşağıdaki snippet, bir istek listesini ( havuzu ) korumanıza ve gerekirse hepsini iptal etmenize olanak tanır . İçinde yere İyi <HEAD>, html'nizin önce başka AJAX çağrıları yapılır.

<script type="text/javascript">
    $(function() {
        $.xhrPool = [];
        $.xhrPool.abortAll = function() {
            $(this).each(function(i, jqXHR) {   //  cycle through list of recorded connection
                jqXHR.abort();  //  aborts connection
                $.xhrPool.splice(i, 1); //  removes from list by index
            });
        }
        $.ajaxSetup({
            beforeSend: function(jqXHR) { $.xhrPool.push(jqXHR); }, //  annd connection to list
            complete: function(jqXHR) {
                var i = $.xhrPool.indexOf(jqXHR);   //  get index for current connection completed
                if (i > -1) $.xhrPool.splice(i, 1); //  removes from list by index
            }
        });
    })
</script>

2
@ mkmurray - IE8 initalization on gibi görünüyor Object doesn't support property or method 'indexOf'? Bunun stackoverflow.com/a/2608601/181971 olabileceğinden şüpheleniyorum veya belki stackoverflow.com/a/2608618/181971 adresine takas edilebilir mi?
Tim

3
@grr haklı, cevabını görün ve dokümanlar için ajaxSetup'ı kontrol edin .
kzfabi

@Tim - Steven'ın önerdiği gibi var index = $ .xhrPool.indexOf (jqXHR) yerine; use: var index = $ .inArray (jqXHR, $ .xhrPool);
Christopher

1
@mkmurray: TypeError gösterir: jqXHR.abort benim için bir işlev değil. :(
Shesha

AbortAll yönteminde küçük bir mantıksal hata var, buradaki yanıt burada düzeltildi stackoverflow.com/a/45500874/1041341
Sarin JS

122

Kullanılması ajaxSetup doğru değil onun doktor sayfasında belirtildiği üzere,. Yalnızca varsayılanları ayarlar ve bazı istekler bunları geçersiz kılarsa bir karışıklık olur.

Partiye çok geç kaldım, ancak sadece aynı soruna bir çözüm arıyorsanız, ileride başvurmak için, işte burada, önceki cevaplardan esinlenilmiş ve büyük ölçüde aynı, ancak daha eksiksiz

// Automatically cancel unfinished ajax requests 
// when the user navigates elsewhere.
(function($) {
  var xhrPool = [];
  $(document).ajaxSend(function(e, jqXHR, options){
    xhrPool.push(jqXHR);
  });
  $(document).ajaxComplete(function(e, jqXHR, options) {
    xhrPool = $.grep(xhrPool, function(x){return x!=jqXHR});
  });
  var abort = function() {
    $.each(xhrPool, function(idx, jqXHR) {
      jqXHR.abort();
    });
  };

  var oldbeforeunload = window.onbeforeunload;
  window.onbeforeunload = function() {
    var r = oldbeforeunload ? oldbeforeunload() : undefined;
    if (r == undefined) {
      // only cancel requests if there is no prompt to stay on the page
      // if there is a prompt, it will likely give the requests enough time to finish
      abort();
    }
    return r;
  }
})(jQuery);

Abort () yöntemini diğer işlevlerden nasıl çağırır?
Stan James

iptal yöntemi bir işlev değil, bir işlevdir. normalde aynı kapsülleme içinden çağırırsınız, kapsülleme dışında kullanmanız gerekiyorsa, işlev adından önce "var" öğesini kaldırabilirsiniz ve bu, tüm dünyada kullanılabilir bir funciton haline gelecektir
Trey

Merhaba, birisi r'nin ne zaman tanımsız olacağını açıklayabilir mi?
Varun

36

İşte bunu gerçekleştirmek için şu anda kullanıyorum.

$.xhrPool = [];
$.xhrPool.abortAll = function() {
  _.each(this, function(jqXHR) {
    jqXHR.abort();
  });
};
$.ajaxSetup({
  beforeSend: function(jqXHR) {
    $.xhrPool.push(jqXHR);
  }
});

Not: _. Underscore.js dosyasının her biri mevcuttur, ancak açıkça gerekli değildir. Ben sadece tembelim ve bunu $ .each () olarak değiştirmek istemiyorum. 8P


2
Sadece göndermek üzere olduğum için harika çalışan biraz değiştirilmiş bir çözümüm var.
mkmurray

7
Bu bellek sızdırıyor. aboutAllöğeleri diziden kaldırmalıdır. Artı, bir istek bittiğinde kendisini listeden kaldırmalıdır.
Behrang Saeedzadeh

5
@BehrangSaeedzadeh Ayrıca daha iyi bir sürüm de yayınlamış olmalısınız.
mattsven

19

Her xhr isteğine benzersiz bir kimlik verin ve nesne başvurusunu göndermeden önce bir nesnede saklayın. Bir xhr isteği tamamlandıktan sonra başvuruyu silin.

Tüm istekleri istediğiniz zaman iptal etmek için:

$.ajaxQ.abortAll();

İptal edilen isteğin benzersiz kimliklerini döndürür. Sadece test amaçlı.

Çalışma fonksiyonu:

$.ajaxQ = (function(){
  var id = 0, Q = {};

  $(document).ajaxSend(function(e, jqx){
    jqx._id = ++id;
    Q[jqx._id] = jqx;
  });
  $(document).ajaxComplete(function(e, jqx){
    delete Q[jqx._id];
  });

  return {
    abortAll: function(){
      var r = [];
      $.each(Q, function(i, jqx){
        r.push(jqx._id);
        jqx.abort();
      });
      return r;
    }
  };

})();

Gerektiğinde daha fazla işlevsellik eklemek için kullanılabilen tek işlevli bir nesne döndürür.


17

Birden fazla istek için çok kolay buldum.

step1: sayfanın üst kısmında bir değişken tanımlayın:

  xhrPool = []; // no need to use **var**

adım2: Tüm ajax istekleri ayarlanan beforeSend:

  $.ajax({
   ...
   beforeSend: function (jqXHR, settings) {
        xhrPool.push(jqXHR);
    },
    ...

step3: istediğiniz yerde kullanın:

   $.each(xhrPool, function(idx, jqXHR) {
          jqXHR.abort();
    });

Bu, stackoverflow.com/a/6618288/1772379 gibi ve tam olarak aynı nedenlerle bellek sızdırıyor .
Ben Johnson

JavaScript yazmak için gerçekten korkunç bir yol.
Ozil

1
sonunda olabilir xhrPool dizi temizleyebilir / boş olabilir
space earth

6

Ben xhrPool.abortAll beklemedeki tüm isteklerini iptal edebilmek için, yukarıda mkmurray ve SpYk3HH cevabı genişletilmiş belirli bir url'nin :

$.xhrPool = [];
$.xhrPool.abortAll = function(url) {
    $(this).each(function(i, jqXHR) { //  cycle through list of recorded connection
        console.log('xhrPool.abortAll ' + jqXHR.requestURL);
        if (!url || url === jqXHR.requestURL) {
            jqXHR.abort(); //  aborts connection
            $.xhrPool.splice(i, 1); //  removes from list by index
        }
    });
};
$.ajaxSetup({
    beforeSend: function(jqXHR) {
        $.xhrPool.push(jqXHR); //  add connection to list
    },
    complete: function(jqXHR) {
        var i = $.xhrPool.indexOf(jqXHR); //  get index for current connection completed
        if (i > -1) $.xhrPool.splice(i, 1); //  removes from list by index
    }
});
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    console.log('ajaxPrefilter ' + options.url);
    jqXHR.requestURL = options.url;
});

AbortAll öğesinin artık isteğe bağlı olarak bir URL'yi parametre olarak kabul edebilmesi ve yalnızca bu URL'ye bekleyen çağrıları iptal etmesi dışında kullanım aynıdır


5

Andy'nin koduyla ilgili bazı problemlerim vardı, ama bana bazı harika fikirler verdi. İlk sorun, başarıyla tamamlanan tüm jqXHR nesnelerini açmamız gerektiğiydi. Ayrıca abortAll işlevini değiştirmek zorunda kaldım. İşte son çalışma kodum:

$.xhrPool = [];
$.xhrPool.abortAll = function() {
            $(this).each(function(idx, jqXHR) {
                        jqXHR.abort();
                        });
};
$.ajaxSetup({
    beforeSend: function(jqXHR) {
            $.xhrPool.push(jqXHR);
            }
});
$(document).ajaxComplete(function() {
            $.xhrPool.pop();
            });

Ben ajaxComplete () şeyler yapmak gibi değildi. Nasıl yapılandırmaya çalıştığım önemli değil. AjaxSetup işe yaramadı.


7
Belirli bir sırayla tamamlanmazlarsa yanlış istek üzerine pop çağırıyor olabilirsiniz?
jjmontes

1
Evet, pop yerine dilim yapmak istiyorsunuz. Göndermek üzere olduğum biraz değiştirilmiş bir çözümüm var.
mkmurray

4

Benim için çalışmasını sağlamak için kodu güncelledim

$.xhrPool = [];
$.xhrPool.abortAll = function() {
    $(this).each(function(idx, jqXHR) {
        jqXHR.abort();
    });
    $(this).each(function(idx, jqXHR) {
        var index = $.inArray(jqXHR, $.xhrPool);
        if (index > -1) {
            $.xhrPool.splice(index, 1);
        }
    });
};

$.ajaxSetup({
    beforeSend: function(jqXHR) {
        $.xhrPool.push(jqXHR);
    },
    complete: function(jqXHR) {
        var index = $.inArray(jqXHR, $.xhrPool);
        if (index > -1) {
            $.xhrPool.splice(index, 1);
        }
    }
});

4

Şapkamı fırlatma. Diziye karşı teklifler abortve removeyöntemler xhrPoolve ajaxSetupgeçersiz kılmalarla ilgili sorunlara eğilimli değil .

/**
 * Ajax Request Pool
 * 
 * @author Oliver Nassar <onassar@gmail.com>
 * @see    http://stackoverflow.com/questions/1802936/stop-all-active-ajax-requests-in-jquery
 */
jQuery.xhrPool = [];

/**
 * jQuery.xhrPool.abortAll
 * 
 * Retrieves all the outbound requests from the array (since the array is going
 * to be modified as requests are aborted), and then loops over each of them to
 * perform the abortion. Doing so will trigger the ajaxComplete event against
 * the document, which will remove the request from the pool-array.
 * 
 * @access public
 * @return void
 */
jQuery.xhrPool.abortAll = function() {
    var requests = [];
    for (var index in this) {
        if (isFinite(index) === true) {
            requests.push(this[index]);
        }
    }
    for (index in requests) {
        requests[index].abort();
    }
};

/**
 * jQuery.xhrPool.remove
 * 
 * Loops over the requests, removes it once (and if) found, and then breaks out
 * of the loop (since nothing else to do).
 * 
 * @access public
 * @param  Object jqXHR
 * @return void
 */
jQuery.xhrPool.remove = function(jqXHR) {
    for (var index in this) {
        if (this[index] === jqXHR) {
            jQuery.xhrPool.splice(index, 1);
            break;
        }
    }
};

/**
 * Below events are attached to the document rather than defined the ajaxSetup
 * to prevent possibly being overridden elsewhere (presumably by accident).
 */
$(document).ajaxSend(function(event, jqXHR, options) {
    jQuery.xhrPool.push(jqXHR);
});
$(document).ajaxComplete(function(event, jqXHR, options) {
    jQuery.xhrPool.remove(jqXHR);
});

2

Tüm ajax isteklerinin bir havuzunu oluşturun ve iptal edin .....

var xhrQueue = []; 

$(document).ajaxSend(function(event,jqxhr,settings){
    xhrQueue.push(jqxhr); //alert(settings.url);
});

$(document).ajaxComplete(function(event,jqxhr,settings){
    var i;   
    if((i=$.inArray(jqxhr,xhrQueue)) > -1){
        xhrQueue.splice(i,1); //alert("C:"+settings.url);
    }
});

ajaxAbort = function (){  //alert("abortStart");
    var i=0;
    while(xhrQueue.length){ 
        xhrQueue[i++] .abort(); //alert(i+":"+xhrQueue[i++]);
    }
};

1

Bağımsız kod kullanmak daha iyi .....

var xhrQueue = []; 

$(document).ajaxSend(function(event,jqxhr,settings){
    xhrQueue.push(jqxhr); //alert(settings.url);
});

$(document).ajaxComplete(function(event,jqxhr,settings){
    var i;   
    if((i=$.inArray(jqxhr,xhrQueue)) > -1){
        xhrQueue.splice(i,1); //alert("C:"+settings.url);
    }
});

ajaxAbort = function (){  //alert("abortStart");
    var i=0;
    while(xhrQueue.length){ 
        xhrQueue[i++] .abort(); //alert(i+":"+xhrQueue[i++]);
    }
};

0

Aynı derecede önemli: oturumu kapatmak istediğinizi ve zamanlayıcılarla yeni istekler oluşturduğunuzu söyleyin: çünkü oturum verileri her yeni önyükleme ile yenilenir (belki Drupal'ı konuştuğumu söyleyebilirsiniz, ancak bu oturumları kullanan herhangi bir site olabilir) .. Tüm senaryolarımı bir arama ve değiştirme ile geçmem gerekiyordu, çünkü farklı durumlarda çalışan bir ton şeyim vardı: üstte küresel değişkenler:

var ajReq = [];
var canAj = true;
function abort_all(){
 for(x in ajReq){
    ajReq[x].abort();
    ajReq.splice(x, 1)
 }
 canAj = false;
}
function rmvReq(ranNum){
 var temp = [];
 var i = 0;
 for(x in ajReq){
    if(x == ranNum){
     ajReq[x].abort();
     ajReq.splice(x, 1);
    }
    i++;
 }
}
function randReqIndx(){
 if(!canAj){ return 0; }
 return Math.random()*1000;
}
function getReqIndx(){
 var ranNum;
 if(ajReq.length){
    while(!ranNum){
     ranNum = randReqIndx();
     for(x in ajReq){
    if(x===ranNum){
     ranNum = null;
    }
     }
    }
    return ranMum;
 }
 return randReqIndx();
}
$(document).ready(function(){
 $("a").each(function(){
    if($(this).attr('href').indexOf('/logout')!=-1){          
     $(this).click(function(){
    abort_all();                 
     });
    }
 })
});
// Then in all of my scripts I wrapped my ajax calls... If anyone has a suggestion for a 
    // global way to do this, please post
var reqIndx = getReqIndx();
if(reqIndx!=0){
ajReq[reqIndx] = $.post(ajax, { 'action': 'update_quantities', iids:iidstr, qtys:qtystr },  
function(data){
 //..do stuff
 rmvReq(reqIndx);
 },'json');
}

0
var Request = {
    List: [],
    AbortAll: function () {
        var _self = this;
        $.each(_self.List, (i, v) => {
            v.abort();
        });
    }
}
var settings = {
    "url": "http://localhost",
    success: function (resp) {
        console.log(resp)
    }
}

Request.List.push($.ajax(settings));

tüm ajax isteğini iptal etmek istediğinizde, bu hattı aramanız yeterlidir

Request.AbortAll()

-2

Tüm ajax isteklerini iptal etmek için kullandığım bir kukla çözüm var. Bu çözüm tüm sayfayı yeniden yüklemektir. Bu çözüm, her ajax isteğine bir kimlik atamak istemiyorsanız ve for-loop içinde ajax istekleri yaparsanız iyidir. Bu, tüm ajax isteklerinin öldürüldüğünden emin olacaktır.

location.reload();

-3

Bunu herhangi bir tıklamaya nasıl bağlayacağınız aşağıda açıklanmıştır (sayfanız birçok AJAX çağrısı yapıyorsa ve uzaklaşmaya çalışıyorsanız).

$ ->
    $.xhrPool = [];

$(document).ajaxSend (e, jqXHR, options) ->
    $.xhrPool.push(jqXHR)

$(document).ajaxComplete (e, jqXHR, options) ->
    $.xhrPool = $.grep($.xhrPool, (x) -> return x != jqXHR);

$(document).delegate 'a', 'click', ->
    while (request = $.xhrPool.pop())
      request.abort()
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.