2009-11-26 7 views

ответ

238

Каждый раз, когда вы создаете запрос Ajax вы можете использовать переменную для ее хранения:

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

Затем вы можете прервать запрос:

request.abort(); 

Вы можете использовать массив отслеживания всех в ожидании запросов ajax и прервать их, если это необходимо.

+10

Да, да, и http://plugins.jquery.com/project/ajaxqueue может помочь. – umpirsky

+0

THXs, я добавил FLAG, потому что я использовал несколько запросов одновременно – jcho360

+0

вот простой рабочий пример: http://stackoverflow.com/a/42312101/3818394 –

36

Вот что я сейчас использую для этого.

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

Примечание: _.ах underscore.js присутствует, но, очевидно, не требуется. Я просто ленив, и я не хочу менять его на $ .each(). 8P

+2

У меня есть слегка измененное решение, которое отлично работает, что я собираюсь опубликовать. – mkmurray

+6

Это утечка памяти. 'aboutAll' должен удалить элементы из массива. Плюс, когда запрос завершен, он должен удалить себя из списка. – Behrang

+3

@BehrangSaeedzadeh Тогда вы должны были также опубликовать улучшенную версию. – mattsven

4

У меня были некоторые проблемы с кодом Andy, но это дало мне отличные идеи. Первая проблема заключалась в том, что мы должны удалять любые объекты jqXHR, которые успешно завершаются. Мне также пришлось изменить функцию abortAll. Вот мой последний рабочий код:

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

Я не люблю ajaxComplete() способ делать вещи. Независимо от того, как я пытался настроить .ajaxSetup, это не сработало.

+7

Я думаю, что вы можете позвонить по неправильному запросу, если они не заполняются в определенном порядке? – jjmontes

+1

Да, вы хотите сделать ломтик вместо поп. У меня есть слегка измененное решение, которое я собираюсь опубликовать. – mkmurray

173

Следующий фрагмент позволяет вам вести список (пул) запроса и прервать их все, если необходимо. Лучше всего разместить в <HEAD> вашего html, до любых других вызовов AJAX.

<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

Ты прибил его. Спасибо – Trip

+2

@mkmurray - при инициализации в IE8 Кажется, я получаю 'Object не поддерживает свойство или метод 'indexOf''? Я подозреваю, что это может быть http://stackoverflow.com/a/2608601/181971 или, может быть, просто поменять на http://stackoverflow.com/a/2608618/181971? – Tim

+3

@grr прав, см. Его ответ и проверьте документы для [ajaxSetup] (http://api.jquery.com/jQuery.ajaxSetup/). – kzfabi

111

Использование ajaxSetup is not correct, как было отмечено на своей странице док. Он устанавливает только значения по умолчанию, и если некоторые запросы переопределяют их, будет беспорядок.

Я опоздал на вечеринку, но только для справки о будущем, если кто-то ищет решение той же проблемы, вот мой взгляд на нее, вдохновленный и в значительной степени идентичный предыдущим ответам, но более полный

// 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); 
+5

Лучше поздно, чем никогда, отличная работа! –

+0

хорошая работа, помогла мне! – devmonster

+0

Как можно вызывать прерывание() из других функций? –

17

Дайте каждому xhr запрос уникального идентификатора и сохраните ссылку на объект в объекте перед отправкой. Удалить ссылку после завершения запроса xhr.

Чтобы отменить все запросы в любое время:

$.ajaxQ.abortAll(); 

Возвращает уникальные идентификаторы отмененного запроса. Только для целей тестирования.

Работа функции:

$.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; 
    } 
    }; 

})(); 

Возвращает объект с одной функцией, которую можно использовать, чтобы добавить больше функциональности при необходимости.

0

Не менее важно: скажите, что вы хотите выйти из системы, и вы генерируете новые запросы с помощью таймеров: потому что данные сеанса обновляются с каждой новой загрузкой (возможно, вы можете сказать, что я говорю о Drupal, но это может быть любой сайт, который использует сессии) ... Я должен был пройти через все мои скрипты с помощью поиска и замены, потому что я была куча вещей работает в разных случаях: глобальные переменные в верхней:

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

Я обновил код сделайте это работает для меня

$.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); 
     } 
    } 
}); 
-3

Вот как подключить этот (полезно, если на вашей странице размещается много вызовов AJAX, и вы пытаетесь перемещаться).

$ -> 
    $.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() 
4

Я продлил mkmurray и SpYk3HH ответ выше, так что xhrPool.abortAll может прервать все ожидающие запросы данного 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; 
}); 

Использование такой же, за исключением того abortAll теперь могут необязательно принимать URL как параметр и отменит только ожидающие вызова на этот URL-адрес

2

Бросок моей шляпы. Предложения abort и remove методы против xhrPool arr ay, и не подвержен проблемам с переопределениями ajaxSetup.

/** 
* Ajax Request Pool 
* 
* @author Oliver Nassar <[email protected]> 
* @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); 
}); 
1

Лучше использовать независимый код .....

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++]); 
    } 
}; 
2

сделать пул всех Ajax запроса и прервать их .....

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++]); 
    } 
}; 
11

Я нашел его слишком легко для нескольких запросов.

step1: определить переменную в верхней части страницы:

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

step2: набор beforeSend во всех Ajax запросов:

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

step3: использовать его везде, где вам требуется :

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

Это работает как есть! –

+0

Я просто хочу, чтобы :) –

+0

Это утечка памяти, как и https://stackoverflow.com/a/6618288/1772379, и по тем же причинам. –

Смежные вопросы