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

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

15.01.2009 12:45:18
Может быть, я неправильно понял вопрос, но не могли бы вы просто использовать $.ajaxStop?
Luke Madhanga 13.09.2013 11:47:00
@LukeMadhanga; Я думаю, что ajaxStopобнаруживает только когда все запросы AJAX завершены, он не останавливает запрос. По моему опыту, вы бы использовать его как это: $(document).ajaxStop(function(){alert("All done")}). Использование .abort()- лучший вариант.
TheCarver 9.12.2013 11:35:50
17 ОТВЕТОВ
РЕШЕНИЕ

Большинство методов 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()

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

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

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

1732
14.07.2018 22:53:50
Это похоже на нажатие кнопки «Стоп» в вашем браузере. Это отменяет запрос. Затем вы можете повторно использовать тот же объект XHR для другого запроса.
meouw 15.01.2009 13:19:49
@brad К сожалению, abortне закрывает установленное соединение с сервером, поэтому successвсе равно будет вызываться. Это очень проблематично для реализаций Comet с длинным опросом.
pepkin88 12.03.2011 12:31:19
@ErvWalter Вы можете отправить еще один запрос, который отменяет предыдущий.
Asad Saeeduddin 9.12.2012 06:37:44
В моих тестах запрос прерывался в браузере, но метод .fail () вызывался с jqXHR, status = 0 и jqXHR, statusMessage = "abort"
BJ Safdie 8.11.2013 02:23:41
.abort()у меня все еще работает в jQuery 3.2.1. Этот комментарий в связанной проблеме github от члена основной команды jQuery, по-видимому, подразумевает, что этот ответ неправильный и .abort() не был удален.
alarive 11.10.2017 10:00:00

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

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

115
3.07.2012 00:28:14

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

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

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

74
15.01.2009 12:56:22
В этом контексте асинхронный просто означает, что запрос не прерывает поток сценария. Браузеры теперь могут преждевременно прервать запрос до его завершения.
ElephantHunter 10.04.2012 19:12:41
Как мы можем отправить запрос на отмену на сервер? Я не понимаю, как сервер будет знать, какой запрос прекратить обработку? Не могли бы вы привести пример? Спасибо.
Lucky Soni 28.06.2014 22:18:58
@LuckySoni, Elephanthunter обсуждает только клиента. На сервер не повлияет запрос .abort
Kloar 11.08.2014 13:28:23
@Kloar, если запрос еще не получен сервером (например, большие многокомпонентные запросы), клиент может закрыть сокет, и сервер будет затронут.
white 20.09.2014 09:17:47
PHP автоматически проверяет прерванные запросы и автоматически завершает работу. см. php.net/manual/en/function.ignore-user-abort.php
hanshenrik 1.03.2015 19:58:39

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

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

67
13.08.2013 15:07:55
поскольку вы всегда отменяете предыдущее, разве вы не всегда можете это сделать? (и не нужно использовать массив)
nonopolarity 21.01.2020 03:02:54

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

  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 (), это может привести к тупиковой ситуации. В наших тестах мы не могли воспроизвести такую ​​ситуацию.

41
28.08.2017 16:38:40

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

Надеюсь это помогло

5
25.07.2013 12:44:11

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

//check for existing ajax request
if(ajax){ 
 ajax.abort();
 }
//then you make another ajax request
$.ajax(
 //your code here
  );
11
8.11.2013 08:07:21

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

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

//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 
13
4.12.2013 14:43:33

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

59
18.03.2015 07:10:46
Из-за предостережения об отмене запроса XHR (см. Другие комментарии на этой странице), это, вероятно, лучший и самый простой вариант.
Quinn Comendant 24.01.2019 00:50:00

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

Проблема, которую я пытался решить (к чему могут также натолкнуться другие), заключается в том, что когда пользователь вводил информацию в поле ввода, я хотел отменить запрос о типе чувствительности 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в консоль непосредственно перед , если блок.

12
3.02.2014 18:43:27

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

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

36
15.10.2014 09:14:27
Я также проверяю, запущен ли уже запрос, но я использую логическое значение, поскольку оно легче.
Please click here 29.07.2015 05:02:27

Просто позвоните 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);
15
10.07.2018 08:07:54

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

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

10
17.06.2015 18:44:24

Следующий код показывает как инициирование, так и прерывание 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="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" class="go" value="GO!" >
   <input type="button" class="stop" value="STOP!" >
7
26.09.2017 14:26:32
Пожалуйста, предоставьте объяснение того, как это решает вопрос. Это поможет ОП и другим будущим поисковикам.
SnareChops 29.01.2016 00:48:14

Я поделился демонстрацией, которая демонстрирует, как отменить запрос 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);   
});
4
12.02.2016 05:25:10
$.ajaxпредоставляет timeoutвозможность, так что вам не нужно писать свои собственные. Просто используйте ..., data: {...}, timeout: waitTime,....
Bram Vanroy 6.07.2016 19:54:02

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

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

// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();
5
23.10.2016 11:56:31

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

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

<script src="http://code.jquery.com/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>
10
18.05.2018 13:17:35