Respostas:
Toda vez que você cria uma solicitação ajax, pode usar uma variável para armazená-la:
var request = $.ajax({
type: 'POST',
url: 'someurl',
success: function(result){}
});
Então você pode abortar a solicitação:
request.abort();
Você pode usar uma matriz para acompanhar todas as solicitações de ajax pendentes e abortá-las, se necessário.
O fragmento a seguir permite manter uma lista ( pool ) de solicitações e interromper todas, se necessário. É melhor colocar no <HEAD>
html antes que outras chamadas AJAX sejam feitas.
<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>
Object doesn't support property or method 'indexOf'
? Eu suspeito que pode ser stackoverflow.com/a/2608601/181971 ou talvez simplesmente trocar para stackoverflow.com/a/2608618/181971 ?
O uso do ajaxSetup não está correto , conforme observado em sua página de documento. Ele apenas configura os padrões e, se alguns pedidos os substituírem, haverá uma bagunça.
Estou muito atrasado para a festa, mas apenas para referência futura, se alguém estiver procurando uma solução para o mesmo problema, aqui está minha chance, inspirado e amplamente idêntico às respostas anteriores, mas mais completo
// 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);
Aqui está o que estou usando atualmente para fazer isso.
$.xhrPool = [];
$.xhrPool.abortAll = function() {
_.each(this, function(jqXHR) {
jqXHR.abort();
});
};
$.ajaxSetup({
beforeSend: function(jqXHR) {
$.xhrPool.push(jqXHR);
}
});
Nota: _.each de underscore.js está presente, mas obviamente não é necessário. Sou apenas preguiçoso e não quero alterá-lo para $ .each (). 8P
aboutAll
deve remover os elementos da matriz. Além disso, quando uma solicitação é concluída, ela deve se remover da lista.
Dê a cada solicitação xhr um ID exclusivo e armazene a referência do objeto em um objeto antes de enviá-lo. Exclua a referência depois que uma solicitação xhr for concluída.
Para cancelar todas as solicitações a qualquer momento:
$.ajaxQ.abortAll();
Retorna os IDs exclusivos da solicitação cancelada. Apenas para fins de teste.
Função de trabalho:
$.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;
}
};
})();
Retorna um objeto com função única que pode ser usada para adicionar mais funcionalidades quando necessário.
Achei muito fácil para várias solicitações.
Etapa 1: defina uma variável no topo da página:
xhrPool = []; // no need to use **var**
step2: configure beforeSend em todas as solicitações de ajax:
$.ajax({
...
beforeSend: function (jqXHR, settings) {
xhrPool.push(jqXHR);
},
...
step3: use-o sempre que necessário:
$.each(xhrPool, function(idx, jqXHR) {
jqXHR.abort();
});
Estendi a resposta mkmurray e SpYk3HH acima para que xhrPool.abortAll possa interromper todas as solicitações pendentes de um determinado URL :
$.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;
});
O uso é o mesmo, exceto que abortAll agora pode aceitar opcionalmente um URL como parâmetro e cancelará apenas as chamadas pendentes para esse URL
Eu tive alguns problemas com o código de Andy, mas isso me deu ótimas idéias. O primeiro problema foi que devemos remover quaisquer objetos jqXHR que foram concluídos com êxito. Eu também tive que modificar a função abortAll. Aqui está o meu código de trabalho final:
$.xhrPool = [];
$.xhrPool.abortAll = function() {
$(this).each(function(idx, jqXHR) {
jqXHR.abort();
});
};
$.ajaxSetup({
beforeSend: function(jqXHR) {
$.xhrPool.push(jqXHR);
}
});
$(document).ajaxComplete(function() {
$.xhrPool.pop();
});
Não gostei da maneira ajaxComplete () de fazer as coisas. Não importa como eu tentei configurar o .ajaxSetup, ele não funcionou.
Atualizei o código para que ele funcione para mim
$.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);
}
}
});
Jogando meu chapéu. Ofertas abort
e remove
métodos contra a xhrPool
matriz e não é propenso a problemas com ajaxSetup
substituições.
/**
* 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);
});
Faça um pool de todas as solicitações de ajax e aborte-as ...
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++]);
}
};
Melhor usar código independente .....
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++]);
}
};
Tão importante quanto: digamos que você deseja fazer logoff e está gerando novas solicitações com temporizadores: porque os dados da sessão são renovados a cada nova inicialização (talvez você possa dizer que estou falando do Drupal, mas esse pode ser qualquer site que utilize sessões) .. Eu tive que passar por todos os meus scripts com uma pesquisa e substituição, porque eu tinha uma tonelada de coisas sendo executadas em diferentes casos: variáveis globais no topo:
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');
}
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));
sempre que você quiser abortar toda a solicitação ajax, basta ligar para esta linha
Request.AbortAll()
Existe uma solução fictícia que eu a uso para abortar todas as solicitações de ajax. Esta solução é recarregar a página inteira. Essa solução é boa se você não gosta de atribuir um ID a cada solicitação ajax e se faz solicitações ajax dentro do loop for. Isso garantirá que todas as solicitações de ajax sejam eliminadas.
location.reload();
Veja como conectar isso a qualquer clique (útil se a sua página estiver fazendo muitas chamadas AJAX e você estiver tentando navegar).
$ ->
$.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()