Прервать Ajax-запросы, используя jQuery

1553

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

  • 2
    Может быть, я неправильно понял вопрос, но не могли бы вы просто использовать $.ajaxStop ?
  • 15
    @LukeMadhanga; Я думаю, что ajaxStop обнаруживает только когда все запросы AJAX завершены, он не останавливает запрос. По моему опыту, вы бы использовали его так: $(document).ajaxStop(function(){alert("All done")}) . Использование .abort() - лучший вариант.
Теги:

19 ответов

1672
Лучший ответ

Большинство методов 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 (документа API jQuery).

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

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

  • 2
    Можете ли вы рассказать, что именно делает abort ()?
  • 5
    @Yuval, developer.mozilla.org/en/XMLHttpRequest#abort ()
Показать ещё 13 комментариев
111

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

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

73

Это запрос асинхронный, что означает, что он отправил его там.

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

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

  • 45
    В этом контексте асинхронный просто означает, что запрос не прерывает поток сценария. Браузеры теперь могут преждевременно прервать запрос до его завершения.
  • 4
    Как мы можем отправить запрос на отмену на сервер? Я не понимаю, как сервер будет знать, какой запрос прекратить обработку? Не могли бы вы привести пример? Спасибо.
Показать ещё 6 комментариев
65

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

HUGE CAVEAT: вы можете прервать запрос, но это только клиентская сторона. Серверная сторона все еще может обрабатывать запрос. Если вы используете что-то вроде PHP или ASP с данными сеанса, данные сеанса блокируются до завершения ajax. Таким образом, чтобы позволить пользователю продолжить просмотр веб-сайта, вы должны вызвать session_write_close(). Это сохраняет сеанс и разблокирует его, чтобы продолжить работу других страниц, ожидающих продолжения. Без этого несколько страниц могут ожидать, что блокировка будет удалена.

43

Запросы 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

  • 0
    Из-за предостережения об отмене запроса XHR (см. Другие комментарии на этой странице) это, вероятно, лучший и самый простой вариант.
37

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

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

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="/jquery.min.js"></script>
<input id="button" type="button" value="click" />

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

29

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

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 нулевым или нет.

  • 2
    Я также проверяю, запущен ли уже запрос, но я использую логическое значение, поскольку оно легче.
19

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

  • 1
    Ссылка неактивна, и снимки веб-архива состоят из 301 страницы ... Я нашел ответвление, которое выглядит так, как будто упомянутый плагин: github.com/aFarkas/Ajaxmanager/blob/master/…
11

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

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

//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 
10

Как отмечают многие люди в потоке, только потому, что запрос прерывается на стороне клиента, сервер все равно обработает запрос. Это создает излишнюю нагрузку на сервер, потому что он выполняет работу, которую мы перестали слушать в интерфейсе.

Проблема, которую я пыталась решить (другие могут зайти в нее), заключается в том, что когда пользователь вводил информацию в поле ввода, я хотел, чтобы я попросил у вас запрос на мгновенный тип Google Instant.

Чтобы избежать стрельбы ненужными запросами и поддерживать привязанность внешнего интерфейса, я сделал следующее:

var xhrQueue = [];
var xhrCount = 0;

$('#search_q').keyup(function(){

    xhrQueue.push(xhrCount);

    setTimeout(function(){

        xhrCount = ++xhrCount;

        if (xhrCount === xhrQueue.length) {
            // Fire Your XHR //
        }

    }, 150);

});

Это будет по существу отправлять один запрос каждые 150 мс (переменную, которую вы можете настроить для своих нужд). Если у вас возникли проблемы с пониманием того, что именно происходит здесь, запишите xhrCount и xhrQueue в консоли непосредственно перед блоком if.

9

Просто позвоните 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);
8

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

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

8

Просто используйте ajax.abort(), например, вы можете прервать любой ожидающий запрос ajax перед отправкой другого, подобного этому

//check for existing ajax request
if(ajax){ 
 ajax.abort();
 }
//then you make another ajax request
$.ajax(
 //your code here
  );
4

В следующем коде показано инициирование, а также прерывание запроса Ajax:

function libAjax(){
  var req;
  function start(){

  req =    $.ajax({
              url: '1.php',
              success: function(data){
                console.log(data)
              }
            });

  }

  function stop(){
    req.abort();
  }

  return {start:start,stop:stop}
}

var obj = libAjax();

 $(".go").click(function(){


  obj.start();


 })



 $(".stop").click(function(){

  obj.stop();


 })
<script src="/jquery.min.js"></script>
<input type="button" class="go" value="GO!" >
   <input type="button" class="stop" value="STOP!" >
  • 5
    Пожалуйста, предоставьте объяснение того, как это решает вопрос. Это поможет ОП и другим будущим поисковикам.
4

У меня возникла проблема опроса, и как только страница была закрыта, опрос продолжался, поэтому по моей причине пользователь пропустил обновление, поскольку значение mysql устанавливалось на следующие 50 секунд после закрытия страницы, хотя я убил ajax запрос, я понял, что при использовании $_SESSION для установки var не будет обновляться в опросе, пока он не закончится, а новый не запустится, поэтому я сделал значение в моей базе данных как 0 = offpage, тогда как Я опроса Я запрашиваю эту строку и возвращаю false; когда он 0 как запрос в опросе, вы получите текущие значения, очевидно...

Я надеюсь, что это помогло

2

Если xhr.abort(); вызывает перезагрузку страницы,

Затем вы можете установить onreadystatechange перед тем, как прервать, чтобы предотвратить:

// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();
2

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

HTML:

<div id="info"></div>

JS CODE:

var isDataReceived= false, waitTime= 1000; 
$(function() {
    // Ajax request sent.
     var xhr= $.ajax({
      url: 'http://api.joind.in/v2.1/talks/10889',
      data: {
         format: 'json'
      },     
      dataType: 'jsonp',
      success: function(data) {      
        isDataReceived= true;
        $('#info').text(data.talks[0].talk_title);        
      },
      type: 'GET'
   });
   // Cancel ajax request if data is not loaded within 1sec.
   setTimeout(function(){
     if(!isDataReceived)
     xhr.abort();     
   },waitTime);   
});
  • 1
    $.ajax предоставляет опцию timeout поэтому вам не нужно писать свой собственный. Просто используйте ..., data: {...}, timeout: waitTime,...
1

Вы можете прервать любой непрерывный вызов ajax, используя этот

<input id="searchbox" name="searchbox" type="text" />

<script src="/jquery-1.11.0.min.js"></script>

<script type="text/javascript">
     var request = null;
        $('#searchbox').keyup(function () {
            var id = $(this).val();
            request = $.ajax({
                type: "POST", //TODO: Must be changed to POST
                url: "index.php",
                data: {'id':id},
                success: function () {

                },
                beforeSend: function () {
                    if (request !== null) {
                        request.abort();
                    }
                }
            });
        });

</script>
-5
$.ajax({
    type: "POST",
    url: "handlername",
    data: "paramerers",
    success: function(msg){
       alert( "Result: " + msg );
    },
    error: function() {
                    alert("Error Message");
                    },
    datatype : JSON,
   async: false,
   cache: false
});

Ещё вопросы

Сообщество Overcoder
Наверх
Меню