Остановите все активные запросы AJAX в JQuery - PullRequest
206 голосов
/ 26 ноября 2009

У меня проблема при отправке формы, все активные ajax-запросы завершаются неудачно, и это вызывает событие ошибки.

Как остановить все активные запросы ajax в jQuery без события ошибки trigerring?

Ответы [ 16 ]

262 голосов
/ 26 ноября 2009

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

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

Тогда вы можете прервать запрос:

request.abort();

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

180 голосов
/ 12 января 2012

Следующий фрагмент позволяет вести список ( пул ) запросов и отменять их все при необходимости. Лучше всего поместить в <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>
119 голосов
/ 22 мая 2012

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

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

// 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);
36 голосов
/ 08 июля 2011

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

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

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

17 голосов
/ 23 июля 2012

Дайте каждому запросу 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;
    }
  };

})();

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

14 голосов
/ 18 февраля 2017

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

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

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

step2: set beforeSend во всех запросах ajax:

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

step3: используйте его там, где вам нужно:

   $.each(xhrPool, function(idx, jqXHR) {
          jqXHR.abort();
    });
5 голосов
/ 26 ноября 2014

Я расширил 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-адрес

5 голосов
/ 12 ноября 2011

У меня были некоторые проблемы с кодом Энди, но это дало мне отличные идеи. Первая проблема заключалась в том, что мы должны выталкивать любые объекты 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, он не работал.

4 голосов
/ 18 января 2013

Я обновил код, чтобы он работал у меня

$.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 голосов
/ 07 марта 2016

Вбрасывание моей шляпы. Предлагает методы abort и remove для массива xhrPool и не подвержено проблемам с переопределениями ajaxSetup.

/**
 * Ajax Request Pool
 * 
 * @author Oliver Nassar <onassar@gmail.com>
 * @see    /863353/ostanovite-vse-aktivnye-zaprosy-ajax-v-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);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...