Question Abandonner les requêtes Ajax en utilisant jQuery


En utilisant jQuery, comment puis-je annuler / annuler une requête Ajax que je n'ai pas encore reçu la réponse de?


1633
2018-01-15 12:45


origine


Réponses:


La plupart des méthodes jQuery Ajax renvoient un objet XMLHttpRequest (ou l'équivalent), donc vous pouvez simplement utiliser abort().

Voir la documentation:

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

METTRE À JOUR: À partir de jQuery 1.5, l'objet retourné est un wrapper pour l'objet XMLHttpRequest natif appelé jqXHR. Cet objet semble exposer toutes les propriétés et méthodes natives de sorte que l'exemple ci-dessus fonctionne toujours. Voir L'objet jqXHR (documentation de l'API jQuery).

MISE À JOUR 2: À partir de jQuery 3, la méthode ajax renvoie maintenant une promesse avec des méthodes supplémentaires (comme l'abandon), donc le code ci-dessus fonctionne toujours, bien que l'objet renvoyé ne soit pas un xhr plus Voir le 3.0 blog ici.

MISE À JOUR 3: xhr.abort() fonctionne toujours sur jQuery 3.x. Ne présumez pas mise à jour 2 est correct. Plus d'infos sur le dépôt jQuery Github.


1592
2018-01-15 12:56



Vous ne pouvez pas rappeler la requête, mais vous pouvez définir une valeur de délai après laquelle la réponse sera ignorée. Regarde ça page pour les options jquery AJAX. Je crois que votre rappel d'erreur sera appelé si le délai d'expiration est dépassé. Il y a déjà un timeout par défaut sur chaque requête AJAX.

Vous pouvez également utiliser le avorter() méthode sur l'objet de requête mais, bien que le client arrête d'écouter l'événement, il mai n'arrêtera probablement pas le serveur de le traiter.


106
2018-01-15 12:55



C'est un asynchrone demande, ce qui signifie qu'une fois qu'il est envoyé, il est là-bas.

Au cas où votre serveur lance une opération très coûteuse à cause de la requête AJAX, le mieux que vous puissiez faire est d'ouvrir votre serveur pour écouter les demandes d'annulation et d'envoyer une requête AJAX séparée pour notifier le serveur d'arrêter ce qu'il fait.

Sinon, ignorez simplement la réponse AJAX.


70
2018-01-15 12:56



Enregistrez les appels que vous effectuez dans un tableau, puis appelez xhr.abort () sur chacun d'entre eux.

CAVEAT ÉNORME: Vous pouvez annuler une demande, mais ce n'est que le côté client. Le côté serveur peut toujours traiter la demande. Si vous utilisez quelque chose comme PHP ou ASP avec des données de session, les données de session sont verrouillées jusqu'à ce que l'ajax soit terminé. Donc, pour permettre à l'utilisateur de continuer à naviguer sur le site, vous devez appeler session_write_close(). Cela enregistre la session et la déverrouille pour que les autres pages en attente de continuer continuent. Sans cela, plusieurs pages peuvent attendre que le verrou soit retiré.


62
2018-03-28 11:34



Les requêtes AJAX peuvent ne pas aboutir dans l'ordre où elles ont été démarrées. Au lieu d'abandonner, vous pouvez choisir de ignorer toutes les réponses AJAX sauf la plus récente:

  • Créer un compteur
  • Incrémenter le compteur lorsque vous lancez une requête AJAX
  • Utilisez la valeur actuelle du compteur pour "marquer" la demande
  • Dans le rappel de réussite, comparez le tampon avec le compteur pour vérifier s'il s'agit de la dernière requête

Ébauche de code:

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

Démo sur jsFiddle


45
2018-01-18 12:55



Nous avons juste dû contourner ce problème et testé trois approches différentes.

  1. annule la demande comme suggéré par @meouw
  2. exécuter toutes les demandes, mais ne traite que le résultat du dernier envoi
  3. empêche les nouvelles demandes tant qu'une autre est toujours en attente

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

Dans notre cas, nous avons décidé d'utiliser l'approche # 3 car elle produit moins de charge pour le serveur. Mais je ne suis pas sûr à 100% si jQuery garantit l'appel de la méthode .complete (), cela pourrait produire une situation de blocage. Dans nos tests, nous n'avons pas pu reproduire une telle situation.


36
2018-03-06 14:29



Il est toujours préférable de faire quelque chose comme ça.

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

Mais c'est beaucoup mieux si vous vérifiez une instruction if pour vérifier si la requête ajax est nulle ou non.


30
2017-10-15 09:14