Отмена запросов Ajax с помощью jQuery

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

Может, я неправильно понял вопрос, но нельзя ли просто использовать $.ajaxStop?

Luke Madhanga 13.09.2013 15:47

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

TheCarver 09.12.2013 15:35
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1 890
2
628 926
18
Перейти к ответу Данный вопрос помечен как решенный

Ответы 18

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

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

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

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

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

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

ElephantHunter 10.04.2012 23:12

Как мы можем отправить на сервер запрос на отмену? Я не понимаю, как сервер узнает, какой запрос прекратить обработку? Не могли бы вы привести пример? Спасибо.

Lucky Soni 29.06.2014 02:18

@LuckySoni, Elephanthunter обсуждает только клиентскую сторону. Запрос .abort не повлияет на сервер

Kloar 11.08.2014 17:28

@Kloar, если запрос еще не получен сервером (например, большие многостраничные запросы), клиент может закрыть сокет, и это повлияет на сервер.

white 20.09.2014 13:17

PHP проверяет прерванные запросы автоматически и также автоматически завершается. см. php.net/manual/en/function.ignore-user-abort.php

hanshenrik 01.03.2015 22:58

@ElephantHunter: не могли бы вы предоставить материалы для чтения по browser aborting request prematurely?

Kishor Pawar 01.06.2016 13:05

@hanshenrik Это правда только наполовину, прочтите документацию, прежде чем публиковать ее. Он работает только в CLI, который широко не используется, особенно для ajax.

Viktor Koncsek 12.07.2017 14:36

@ViktorKoncsek нет, ignore_user_abort () также предназначен для веб-запросов (например, php + Apache)

hanshenrik 12.07.2017 23:33
Ответ принят как подходящий

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

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

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

Не могли бы вы подробнее рассказать, что именно делает abort ()?

Yuval Adam 15.01.2009 16:04

Это похоже на нажатие кнопки «Стоп» в браузере. Он отменяет запрос. Затем вы можете повторно использовать тот же объект XHR для другого запроса.

meouw 15.01.2009 16:19

@brad К сожалению, abort не закрывает установленное соединение с сервером, поэтому success все равно будет вызываться. Это очень проблематично для реализаций Comet с длинным опросом.

pepkin88 12.03.2011 15:31

@ErvWalter Вы можете отправить другой запрос, который отменяет предыдущий.

Asad Saeeduddin 09.12.2012 10:37

@JoeCoderGuy: Я не уверен. Сервер по-прежнему будет делать это, но в моих тестах (по крайней мере, в Chrome v23) метод успеха javascript не вызывается.

user420667 29.12.2012 21:27

@ user420667 У меня должна быть странная версия, потому что она не отменяет мою (та же версия). Я видел по другому вопросу, что выполнение этого на локальном хосте может не дать достаточно времени для отмены stackoverflow.com/questions/8584402/…

user1382306 29.12.2012 23:44

В моих тестах запрос прерывается в браузере, но метод .fail () вызывается с jqXHR, status = 0 и jqXHR, statusMessage = "abort"

BJ Safdie 08.11.2013 06:23

для nodejs вызовите req.on('close', function() { }), чтобы определить, вызвала ли сторона javascript .abort()

Funkodebat 08.05.2014 22:24

В некоторых случаях я заметил, что нажатие и удерживание кнопки выхода отменяет запросы AJAX.

shasi kanth 14.07.2014 13:11

Он больше не будет работать для jQuery 3.0 blog.jquery.com/2016/01/14/jquery-3-0-beta-released

jcubic 31.01.2016 16:05

вы можете использовать return false, если выполняется определенное условие

Umair Khan 05.04.2016 18:08

Поскольку это такой высокий ответ, в нем действительно должно быть отражено, что это больше не работает (как упомянул @jcubic)

anson 18.05.2017 22:34
.abort() у меня все еще работает в jQuery 3.2.1. Этот комментарий в связанной проблеме github члена основной группы jQuery, похоже, подразумевает, что этот ответ неверен и что .abort() не был удален.
alarive 11.10.2017 13:00

выдает ошибку для AjaxHelper: .abort () не является функцией

Vikrant 28.11.2018 13:52

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

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

поскольку вы всегда отменяете предыдущий, разве вы не можете просто всегда это делать? (и нет необходимости использовать массив)

nonopolarity 21.01.2020 06:02

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

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

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

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

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

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

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

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

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

Запросы 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.info("Process the response");
        } else {
            console.info("Ignore the response");
        }
    });
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last 
// one will trigger "Process the response" message

Демо на jsFiddle

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

Quinn Comendant 24.01.2019 03:50

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

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

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

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

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

Zesty 29.07.2015 08:02

Просто вызовите xhr.прерывание (), будь то объект 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);

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

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

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

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

  req =    $.ajax({
              url: '1.php',
              success: function(data){
                console.info(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!" >

Пожалуйста, объясните, как это решает вопрос. Это поможет OP и другим будущим поисковикам.

SnareChops 29.01.2016 03:48

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

HTML:

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

КОД JS:

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);   
});
$.ajax предоставляет опцию timeout, поэтому вам не нужно писать свою собственную. Просто используйте ..., data: {...}, timeout: waitTime,....
Bram Vanroy 06.07.2016 22:54

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

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

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

Вы можете прервать любой непрерывный вызов 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>

Это моя реализация, основанная на многих ответах выше:

  var activeRequest = false; //global var
  var filters = {...};
  apply_filters(filters);

  //function triggering the ajax request
  function apply_filters(filters){
        //prepare data and other functionalities
        var data = {};
        //limit the ajax calls
        if (activeRequest === false){
          activeRequest = true;
        }else{
          //abort if another ajax call is pending
          $request.abort();
          //just to be sure the ajax didn't complete before and activeRequest it's already false
          activeRequest = true;        
        }

        $request = $.ajax({ 
          url : window.location.origin + '/your-url.php',
          data: data,
          type:'POST',
          beforeSend: function(){
            $('#ajax-loader-custom').show();
            $('#blur-on-loading').addClass('blur');
          },            
          success:function(data_filters){

              data_filters = $.parseJSON(data_filters);
              
              if ( data_filters.posts ) {
                  $(document).find('#multiple-products ul.products li:last-child').after(data_filters.posts).fadeIn();
              }
              else{ 
                return;
              }
              $('#ajax-loader-custom').fadeOut();
          },
          complete: function() {
            activeRequest = false;
          }          
        }); 
  } 

Другие вопросы по теме