Питання Скасувати запити Ajax, використовуючи jQuery


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


1637
2018-01-15 12:45


походження


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


Відповіді:


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

UPDATE 2: Що стосується jQuery 3, метод ajax тепер повертає обіцянку додатковими методами (наприклад, abort), тож вказаний код все ще працює, хоча об'єкт, що повертається, не є xhr більше. Див Блог 3.0 тут.

UPDATE 3: xhr.abort() все ще працює на jQuery 3.x. Не вважай, що оновлення 2 правильно. Докладніше про репозиторій jQuery Github.


1597
2018-01-15 12:56



Це нагадує натискання кнопки "зупинити" у вашому веб-переглядачі. Це скасовує запит. Потім ви можете повторно використовувати один і той же об'єкт XHR для іншого запиту. - meouw
@brad На жаль, abort не закриває встановлене з'єднання з сервером, так що success буде ще називатися. Це дуже проблематично для реалізації Комети з тривалим опитуванням. - pepkin88
@ErvWalter Ви можете надіслати інший запит, який скасовує попередній. - Asad Saeeduddin
У моїх тестах запит перервано в браузері, але метод .fail () викликається з jqXHR, status = 0 і jqXHR, statusMessage = "abort" - BJ Safdie
Він більше не буде працювати для jQuery 3.0 blog.jquery.com/2016/01/14/jquery-3-0-beta- опубліковано - jcubic


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

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


106
2018-01-15 12:55





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

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

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


70
2018-01-15 12:56



У цьому контексті асинхронний просто означає, що запит не перериває потік скрипту. Тепер браузери мають змогу перервати запит перед тим, як запит буде завершено. - ElephantHunter
Як ми можемо відправити запит скасування на сервер? Я не розумію, як сервер буде знати, який запит зупинити обробку? Не могли б ви навести приклад? Дякую. - Lucky Soni
@ LuckySoni, Elephanthunter лише обговорює клієнтську сторону. На сервер не впливає запит .abort - Kloar
@Kloar, якщо запит ще не отримано сервером (f.ex. великі багатопроцесні запити), клієнт може закрити сокет, і на нього буде вплинути сервер. - white
PHP перевіряє автоматично скасовані запити та автоматично закінчує роботу. побачити php.net/manual/en/function.ignore-user-abort.php - hanshenrik


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

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


62
2018-03-28 11:34





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


45
2018-01-18 12:55





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

  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, оскільки він виробляє меншу навантаження для сервера. Але я не впевнений, що якщо jQuery гарантує виклик методу .complete (), це може призвести до ситуації в тупиковій ситуації. У наших тестах ми не могли відтворити таку ситуацію.


36
2018-03-06 14: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);
    });

Але це набагато краще, якщо ви перевіряєте statement if, щоб перевірити, чи є запит ajax нульовим чи ні.


30
2017-10-15 09:14



Я також перевірюю, чи запрошення вже запущено, але я використовую логічний, так як воно легше. - Zesty


рішення Meouw це правильно, але якщо ви зацікавлені в більш контрольованому, то ви можете спробувати Плагін менеджера Ajax для jQuery.


19
2018-01-15 15:45



Посилання мертва, а знімки веб-архіву - 301 сторінок ... Я знайшов вилку, яка виглядає так, як згадав плагін: github.com/aFarkas/Ajaxmanager/blob/master/... - brasofilo


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

У моєму випадку я використовував щось на зразок цього:

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

11
2017-12-04 14:43





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

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


10
2018-02-03 18:43