Прервать Ajax-запросы, используя jQuery - PullRequest
1741 голосов
/ 15 января 2009

Используя jQuery, как я могу отменить / отменить запрос Ajax , от которого я еще не получил ответ?

Ответы [ 18 ]

1677 голосов
/ 15 января 2009

Большинство методов jQuery Ajax возвращают объект XMLHttpRequest (или эквивалентный), поэтому вы можете просто использовать abort().

См. Документацию:

var xhr = $.ajax({
    type: "POST",
    url: "some.php",
    data: "name=John&location=Boston",
    success: function(msg){
       alert( "Data Saved: " + msg );
    }
});

//kill the request
xhr.abort()

UPDATE: Начиная с jQuery 1.5 возвращаемый объект является оберткой для собственного объекта XMLHttpRequest с именем jqXHR. Этот объект, по-видимому, предоставляет все собственные свойства и методы, поэтому приведенный выше пример все еще работает. См. Объект jqXHR (документация по jQuery API).

ОБНОВЛЕНИЕ 2: Начиная с jQuery 3, метод ajax теперь возвращает обещание с дополнительными методами (например, abort), поэтому приведенный выше код все еще работает, хотя возвращаемый объект больше не является xhr. Смотрите блог 3.0 здесь .

ОБНОВЛЕНИЕ 3 : xhr.abort() по-прежнему работает в jQuery 3.x. Не думайте, что обновление 2 является правильным. Подробнее о репозитории jQuery Github .

111 голосов
/ 15 января 2009

Вы не можете отозвать запрос, но вы можете установить значение тайм-аута, после которого ответ будет игнорироваться. Смотрите эту страницу для опций jquery AJAX. Я считаю, что ваш обратный вызов ошибки будет вызван, если превышен период ожидания. У каждого запроса AJAX уже есть тайм-аут по умолчанию.

Вы также можете использовать метод abort () для объекта запроса, но, хотя это приведет к тому, что клиент прекратит прослушивать событие, он может , вероятно, не остановит сервер от его обработки.

72 голосов
/ 15 января 2009

Это асинхронный запрос, то есть, когда он отправлен, он уже существует.

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

В противном случае просто игнорируйте ответ AJAX.

65 голосов
/ 28 марта 2012

Сохраните вызовы, которые вы делаете, в массиве, затем вызовите xhr.abort () для каждого.

ОГРОМНАЯ ПРОСМОТР: Вы можете прервать запрос, но это только на стороне клиента. Серверная сторона все еще может обрабатывать запрос. Если вы используете что-то вроде PHP или ASP с данными сеанса, данные сеанса блокируются до завершения Ajax. Таким образом, чтобы позволить пользователю продолжить просмотр веб-сайта, вы должны вызвать session_write_close (). Это сохранит сеанс и разблокирует его, так что другие страницы, ожидающие продолжения, продолжатся. Без этого несколько страниц могут ожидать снятия блокировки.

53 голосов
/ 18 января 2014

AJAX-запросы могут не выполняться в том порядке, в котором они были запущены. Вместо прерывания вы можете игнорировать все ответы AJAX, за исключением самого последнего:

  • Создать счетчик
  • Увеличение счетчика при запуске запроса AJAX
  • Использовать текущее значение счетчика для "штампования" запроса
  • В обратном вызове успеха сравните штамп со счетчиком, чтобы проверить, был ли это самый последний запрос

Грубый набросок кода:

var xhrCount = 0;
function sendXHR() {
    // sequence number for the current invocation of function
    var seqNumber = ++xhrCount;
    $.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {
        // this works because of the way closures work
        if (seqNumber === xhrCount) {
            console.log("Process the response");
        } else {
            console.log("Ignore the response");
        }
    });
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last 
// one will trigger "Process the response" message

Демонстрация на jsFiddle

39 голосов
/ 06 марта 2013

Нам просто пришлось обойти эту проблему и протестировать три разных подхода.

  1. отменяет запрос, предложенный @ meouw
  2. выполнить все запросы, но обрабатывает только результат последней отправки
  3. предотвращает новые запросы до тех пор, пока другой еще ожидает

var Ajax1 = {
  call: function() {
    if (typeof this.xhr !== 'undefined')
      this.xhr.abort();
    this.xhr = $.ajax({
      url: 'your/long/running/request/path',
      type: 'GET',
      success: function(data) {
        //process response
      }
    });
  }
};
var Ajax2 = {
  counter: 0,
  call: function() {
    var self = this,
      seq = ++this.counter;
    $.ajax({
      url: 'your/long/running/request/path',
      type: 'GET',
      success: function(data) {
        if (seq === self.counter) {
          //process response
        }
      }
    });
  }
};
var Ajax3 = {
  active: false,
  call: function() {
    if (this.active === false) {
      this.active = true;
      var self = this;
      $.ajax({
        url: 'your/long/running/request/path',
        type: 'GET',
        success: function(data) {
          //process response
        },
        complete: function() {
          self.active = false;
        }
      });
    }
  }
};
$(function() {
  $('#button').click(function(e) {
    Ajax3.call();
  });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="button" type="button" value="click" />

В нашем случае мы решили использовать подход № 3, так как он создает меньшую нагрузку на сервер. Но я не уверен на 100%, если jQuery гарантирует вызов метода .complete (), это может привести к тупиковой ситуации. В наших тестах мы не могли воспроизвести такую ​​ситуацию.

34 голосов
/ 15 октября 2014

Всегда лучше делать что-то подобное.

var $request;
if ($request != null){ 
    $request.abort();
    $request = null;
}

$request = $.ajax({
    type : "POST", //TODO: Must be changed to POST
    url : "yourfile.php",
    data : "data"
    }).done(function(msg) {
        alert(msg);
    });

Но гораздо лучше, если вы проверите оператор if, чтобы проверить, является ли запрос ajax нулевым или нет.

20 голосов
/ 15 января 2009

решение meouw правильно, но если вы заинтересованы в большем контроле, вы можете попробовать плагин Ajax Manager для jQuery.

13 голосов
/ 28 мая 2015

Просто вызовите xhr. abort () , будь то объект jquery ajax или собственный объект XMLHTTPRequest.

пример:

//jQuery ajax
$(document).ready(function(){
    var xhr = $.get('/server');
    setTimeout(function(){xhr.abort();}, 2000);
});

//native XMLHTTPRequest
var xhr = new XMLHttpRequest();
xhr.open('GET','/server',true);
xhr.send();
setTimeout(function(){xhr.abort();}, 2000);
12 голосов
/ 04 декабря 2013

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

В моем случае я использовал что-то вроде этого:

//On document ready
var ajax_inprocess = false;

$(document).ajaxStart(function() {
ajax_inprocess = true;
});

$(document).ajaxStop(function() {
ajax_inprocess = false;
});

//Snippet from live search function
if (ajax_inprocess == true)
{
    request.abort();
}
//Call for new request 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...