Pytanie Przerwij żądania Ajax za pomocą jQuery


Korzystając z jQuery, jak mogę anuluj / anuluj żądanie Ajax że jeszcze nie otrzymałem odpowiedzi?


1637
2018-01-15 12:45


pochodzenie


Może źle zrozumiałem to pytanie, ale nie mogłeś po prostu użyć $.ajaxStop? - Luke Madhanga
@LukeMadhanga; Myślę ajaxStop wykrywa tylko wtedy, gdy wszystkie żądania AJAX są kompletne, nie zatrzymuje żądania. Z mojego doświadczenia wynika, że ​​używałbyś go tak: $(document).ajaxStop(function(){alert("All done")}). Za pomocą .abort() jest najlepszą opcją. - TheCarver


Odpowiedzi:


Większość metod Ajax jQuery zwraca obiekt XMLHttpRequest (lub równoważny), więc możesz po prostu użyć abort().

Zobacz dokumentację:

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()

AKTUALIZACJA: Od wersji jQuery 1.5 zwracany obiekt jest opakowaniem dla natywnego obiektu XMLHttpRequest o nazwie jqXHR. Ten obiekt wydaje się eksponować wszystkie natywne właściwości i metody, więc powyższy przykład nadal działa. Widzieć Obiekt jqXHR (dokumentacja API jQuery).

UPDATE 2: Jak w przypadku jQuery 3, metoda ajax zwraca teraz obietnicę z dodatkowymi metodami (jak na przykład abort), więc powyższy kod nadal działa, chociaż zwracany obiekt nie jest xhr nie więcej. Zobacz 3.0 blog tutaj.

AKTUALIZACJA 3: xhr.abort() nadal działa na jQuery 3.x. Nie zakładaj aktualizacja 2 jest poprawne. Więcej informacji na temat repozytorium jQuery Github.


1597
2018-01-15 12:56



To tak, jakby kliknąć przycisk "stop" w przeglądarce. Anuluje żądanie. Następnie możesz ponownie użyć tego samego obiektu XHR dla innego żądania. - meouw
@brad Niestety, abort nie zamyka ustalonego połączenia z serwerem, czyli success będą nadal wywoływane. Jest to bardzo problematyczne dla implementacji Cometa z długim sondowaniem. - pepkin88
@ErvWalter Możesz wysłać następną prośbę, która anuluje poprzednią. - Asad Saeeduddin
W moich testach żądanie jest przerywane w przeglądarce, ale metoda .fail () jest wywoływana za pomocą jqXHR, status = 0 i jqXHR, statusMessage = "abort" - BJ Safdie
To nie będzie działać dla jQuery 3.0 blog.jquery.com/2016/01/14/jquery-3-0-beta-released - jcubic


Nie można przywołać żądania, ale można ustawić wartość limitu czasu, po którym odpowiedź zostanie zignorowana. Zobacz strona dla opcji AJAX jquery. Wierzę, że Twój callback błędu zostanie wywołany, jeśli przekroczony zostanie limit czasu. Na każdym żądaniu AJAX istnieje już domyślny limit czasu.

Możesz także użyć anulować() metoda na obiekcie żądania, ale spowoduje to, że klient przestanie nasłuchiwać zdarzenia może prawdopodobnie nie powstrzyma serwera przed jego przetworzeniem.


106
2018-01-15 12:55





To jest asynchroniczny prośba, co oznacza, że ​​po wysłaniu jest tam.

W przypadku, gdy twój serwer rozpoczyna bardzo kosztowną operację z powodu żądania AJAX, najlepiej jest otworzyć serwer, aby wysłuchać żądań anulowania, i wysłać oddzielne żądanie AJAX powiadamiające serwer, aby przestał robić to, co robi.

W przeciwnym razie po prostu zignoruj ​​odpowiedź AJAX.


70
2018-01-15 12:56



W tym kontekście asynchroniczny oznacza po prostu, że żądanie nie przerywa przepływu skryptu. Przeglądarki mogą teraz przedwcześnie anulować żądanie przed zakończeniem żądania. - ElephantHunter
Jak wysłać żądanie anulowania na serwer? Nie rozumiem, w jaki sposób serwer będzie wiedział, które żądanie przerwać przetwarzanie? Czy mógłbyś podać przykład? Dziękuję Ci. - Lucky Soni
@LuckySoni, Elephanthunter rozmawia tylko o stronie klienta. Serwer nie będzie podlegał wpływowi żądania .abort - Kloar
@Kloar, jeśli żądanie nie zostało jeszcze odebrane przez serwer (na przykład duże żądania multpart), klient może zamknąć gniazdo, a serwer zostanie dotknięty. - white
PHP sprawdza automatycznie przerwane żądania i automatycznie je kończy. widzieć php.net/manual/en/function.ignore-user-abort.php - hanshenrik


Zapisz połączenia, które wywołujesz w tablicy, a następnie wywołaj xhr.abort () na każdym z nich.

OGROMNY PRZEGLĄD: Możesz przerwać żądanie, ale to tylko strona klienta. Strona serwera może nadal przetwarzać żądanie. Jeśli używasz czegoś takiego jak PHP lub ASP z danymi sesji, dane sesji są zablokowane, dopóki ajax nie skończy. Aby umożliwić użytkownikowi kontynuowanie przeglądania strony internetowej, musisz zadzwonić session_write_close(). To zapisze sesję i odblokuje ją, aby inne strony oczekujące na kontynuację będą kontynuowane. Bez tego kilka stron może oczekiwać na usunięcie blokady.


62
2018-03-28 11:34





Żądania AJAX mogą nie kończyć się w kolejności, w jakiej zostały uruchomione. Zamiast przerwać, możesz wybrać ignorować wszystkie odpowiedzi AJAX z wyjątkiem najnowszego:

  • Utwórz licznik
  • Zwiększ licznik, gdy zainicjujesz żądanie AJAX
  • Użyj bieżącej wartości licznika, aby "nadpisać" żądanie
  • W callback powodzenia porównaj stempel z licznikiem, aby sprawdzić, czy było to ostatnie żądanie

Szorstki zarys kodu:

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

Demo na jsFiddle


45
2018-01-18 12:55





Po prostu musieliśmy obejść ten problem i przetestowaliśmy trzy różne podejścia.

  1. anuluje żądanie zgodnie z sugestią @meouw
  2. wykonać wszystkie żądania, ale przetwarza tylko wynik ostatniego przesłania
  3. zapobiega nowym żądaniom, dopóki trwa jeszcze jedno

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

W naszym przypadku zdecydowaliśmy się na podejście nr 3, ponieważ powoduje to mniejsze obciążenie serwera. Ale nie jestem w 100% pewny, czy jQuery gwarantuje wywołanie metody .complete () - może to spowodować sytuację impasu. W naszych testach nie mogliśmy odtworzyć takiej sytuacji.


36
2018-03-06 14:29





Najlepszą praktyką jest robienie czegoś takiego.

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);
    });

Ale jest znacznie lepiej, jeśli sprawdzisz instrukcję if, aby sprawdzić, czy żądanie ajax jest puste, czy nie.


30
2017-10-15 09:14



Sprawdzam również, czy żądanie jest już uruchomione, ale używam boolean, ponieważ jest lżejszy. - Zesty


rozwiązanie meouw jest poprawny, ale jeśli jesteś zainteresowany większą kontrolą, możesz spróbować Wtyczka Ajax Manager dla jQuery.


19
2018-01-15 15:45



Link jest martwy, a migawki z Archiwum sieci są 301 stronami ... Znalazłem widelec, który wygląda jak wspomniana wtyczka: github.com/aFarkas/Ajaxmanager/blob/master/... - brasofilo


Robiłem rozwiązanie do wyszukiwania na żywo i musiałem anulować oczekujące żądania, które mogły potrwać dłużej niż najnowsze / najbardziej aktualne żądanie.

W moim przypadku użyłem czegoś takiego:

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