Скасувати запити Ajax за допомогою jQuery


1827

Як користуватися jQuery, як я можу скасувати / скасувати запит Ajax, на який я ще не отримав відповіді?


2
Можливо, я неправильно зрозумів питання, але ви не могли просто скористатися $.ajaxStop?
Люк Мадханга

17
@LukeMadhanga; Я думаю, що ajaxStopвиявляється лише тоді, коли всі запити AJAX завершені, це не зупиняє запит. З мого досвіду, ви б використовувати його як це: $(document).ajaxStop(function(){alert("All done")}). Використання .abort()- найкращий варіант.
TheCarver

Відповіді:


1744

Більшість методів 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 тепер повертає обіцянку додатковими методами (наприклад, перервати), тому вищезазначений код все ще працює, хоча об'єкт, який повертається, вже не є xhr. Дивіться блог 3.0 тут .

ОНОВЛЕННЯ 3 : xhr.abort()все ще працює на jQuery 3.x. Не вважайте, що оновлення 2 правильне. Детальніше про сховище jQuery Github .


12
Це як натиснути кнопку "стоп" у вашому браузері. Він скасовує запит. Потім ви можете повторно використовувати той самий об’єкт XHR для іншого запиту.
meouw

65
@brad На жаль, abortне встановлено зв’язок із сервером, тому successвін все ще буде викликаний. Це дуже проблематично для впровадження Comet із тривалими опитуваннями.
pepkin88

6
@ErvWalter Ви можете відправити ще один запит, який скасовує попередній.
Асад Саєдюддін

8
У моїх тестах запит перервано у веб-переглядачі, але метод .fail () викликається jqXHR, status = 0 і jqXHR, statusMessage = "abort"
BJ Safdie

9
.abort()все ще працює для мене в jQuery 3.2.1. Цей коментар у спорідненому випуску github члена основної команди jQuery, здається, означає, що ця відповідь невірна і .abort() її не було видалено.
аларів

117

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

Ви можете також використовувати переривання () метод об'єкта запиту , але, в той час як це призведе до клієнта , щоб зупинити прослуховування події, він може , ймовірно , буде не зупинити сервер від обробки.


74

Це асинхронний запит, тобто щоразу, коли він надсилається, він знаходиться там.

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

В іншому випадку просто ігноруйте відповідь AJAX.


48
У цьому контексті асинхронність просто означає, що запит не перериває потік сценарію. Зараз браузери мають можливість передчасно скасувати запит до завершення запиту.
ElephantHunter

4
Як ми можемо надіслати запит на скасування на сервер? Я не розумію, як сервер дізнається, на який запит припинити обробку? Чи можете ви навести приклад? Дякую.
Lucky Soni

3
@LuckySoni, Elephanthunter обговорює лише сторону клієнта. Запит
.abort на

4
@Kloar, якщо сервер ще не отримав запит (f.ex. великі багатозахисні запити), клієнт може закрити сокет, і сервер буде вплинутий.
білий

4
PHP перевіряє наявність перерваних запитів автоматично, а також автоматично припиняється. дивіться php.net/manual/en/function.ignore-user-abort.php
hanshenrik

68

Збережіть дзвінки, які ви здійснюєте в масиві, а потім зателефонуйте xhr.abort () на кожен.

ВЕЛИЧИЙ КАЙВАТ: Ви можете скасувати запит, але це лише сторона клієнта. Сторона сервера все ще може обробляти запит. Якщо ви використовуєте щось на зразок PHP або ASP з даними сеансу, дані сеансу блокуються до завершення ajax. Отже, щоб дозволити користувачу продовжувати перегляд веб-сайту, вам потрібно зателефонувати session_write_close (). Це зберігає сеанс і розблоковує його так, що інші сторінки, які чекають на продовження, продовжуватимуться. Без цього кілька сторінок можуть чекати, коли замок буде знято.


оскільки ви завжди скасовуєте попереднє, чи не завжди ви можете це робити? (і не потрібно використовувати масив)
nopopolarity

60

Запити 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


Через застереження щодо скасування запиту XHR (див. Інші коментарі на цій сторінці), це, мабуть, найкращий і найпростіший варіант.
Квінн Комендант

41

Нам просто довелося вирішити цю проблему і перевірити три різні підходи.

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


36

Це завжди найкраща практика робити щось подібне.

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
Я також перевіряю, чи запит вже запущений, але я використовую булевий, оскільки він легший.
Будь ласка, натисніть тут

15

Просто зателефонуйте 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);

13

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

У моєму випадку я використовував щось подібне:

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

12

Як зауважило багато людей у ​​потоці, лише тому, що запит перервано на стороні клієнта, сервер все ще обробляє запит. Це створює непотрібне навантаження на сервер, оскільки він робить роботу, яку ми кинули слухати на передній частині.

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

Щоб уникнути запуску непотрібних запитів і підтримати простоту переднього телефону, я зробив наступне:

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.


11

Просто використовуйте ajax.abort (), наприклад, ви можете скасувати будь-який очікуваний запит на ajax, перш ніж надсилати ще один подібний

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

11

Ви можете скасувати будь-який безперервний дзвінок 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

немає надійного способу це зробити, і я б навіть не намагався цього разу, як тільки запит буде в дорозі; тільки спосіб реагувати розумно, щоб ігнорувати реакцію.

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


7

У наведеному нижче коді показано ініціювання, а також припинення запиту 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!" >

5
Будь ласка, надайте пояснення, як це вирішує питання. Це допоможе ОП та іншим майбутнім шукачам.
SnareChops

5

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

Я сподіваюся, що це допомогло


5

Якщо xhr.abort(); причини перезавантаження сторінки,

Потім ви можете встановити onreadystatechangeперед абортом, щоб запобігти:

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

4

Я поділився демонстрацією, яка демонструє, як скасувати запит 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);   
});

1
$.ajaxнадає timeoutможливість, тому вам не потрібно писати свій власний. Просто використовуйте ..., data: {...}, timeout: waitTime,....
Брем Ванрой
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.