web-dev-qa-db-fra.com

Abandonner les requêtes Ajax avec jQuery

Avec jQuery, comment puis-je annuler/annuler une demande Ajax dont je n'ai pas encore reçu la réponse?

1760
lukewm

La plupart des méthodes jQuery Ajax renvoient un objet XMLHttpRequest (ou équivalent), vous pouvez donc 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()

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

UPDATE 2: À partir de jQuery 3, la méthode ajax renvoie désormais une promesse avec des méthodes supplémentaires (comme abort), de sorte que le code ci-dessus fonctionne toujours, bien que L'objet renvoyé n'est plus un xhr. Voir le .0 blog here .

UPDATE 3 : xhr.abort() fonctionne toujours sur jQuery 3.x. Ne supposez pas que la mise à jour 2 est correcte. Plus d'informations sur le référentiel jQuery Github .

1688
meouw

Vous ne pouvez pas rappeler la demande, mais vous pouvez définir une valeur de délai après laquelle la réponse sera ignorée. Voir ceci page pour jquery AJAX options. Je crois que votre rappel d'erreur sera appelé si le délai d'attente est dépassé. Il existe déjà un délai d’expiration par défaut pour chaque demande AJAX.

Vous pouvez également utiliser la méthode abort () sur l'objet de la requête mais, même si cela oblige le client à arrêter d'écouter l'événement, il mai n'empêchera probablement pas le serveur de le traiter.

111
tvanfosson

C'est une demande asynchrone, ce qui signifie qu'une fois envoyée, elle est envoyée.

Si votre serveur démarre une opération très coûteuse en raison de la demande AJAX, le mieux que vous puissiez faire est d'ouvrir votre serveur pour écouter les demandes d'annulation et d'envoyer une demande AJAX distincte. le serveur pour arrêter quoi que ce soit.

Sinon, ignorez simplement la réponse AJAX.

72
Yuval Adam

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

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

66
Tei

Les demandes AJAX peuvent ne pas se terminer dans l'ordre dans lequel elles ont été démarrées. Au lieu d'abandonner, vous pouvez choisir d'ignorer toutes les réponses AJAX à l'exception de la plus récente:

  • Créer un compteur
  • Incrémenter le compteur lorsque vous lancez la demande AJAX
  • Utilisez la valeur actuelle de counter pour "tamponner" la requête
  • Dans le rappel de réussite, comparez le tampon avec le compteur pour vérifier s’il s’agissait de la demande la plus récente.

Contour approximatif du 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

55
Salman A

Nous devions simplement contourner ce problème et tester 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 n ° 3, car elle génère moins de charge pour le serveur. Mais je ne suis pas sûr à 100% que si jQuery garantisse l'appel de la méthode .complete () -, cela pourrait produire une situation de blocage. Dans nos tests, nous ne pouvions pas reproduire une telle situation.

40
oyophant

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 il est bien préférable de vérifier une instruction if pour vérifier si la requête ajax est nulle ou non.

35
Tharindu Kumara

la solution de meouw est correct, mais si vous souhaitez davantage de contrôle, vous pouvez essayer le plugin Ajax Manager pour jQuery.

20
Prestaul

Il suffit d'appeler xhr .abort (), qu'il s'agisse d'un objet jquery ajax ou d'un objet XMLHTTPRequest natif.

exemple:

//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);
14
cuixiping

Je faisais une solution de recherche en direct et je devais annuler les demandes en attente pouvant avoir pris plus de temps que la demande la plus récente/la plus récente.

Dans mon cas, j'ai utilisé quelque chose comme ceci:

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

Comme de nombreuses personnes sur le thread l'ont noté, le serveur traitera toujours la demande simplement parce que la demande est abandonnée du côté client. Cela crée une charge inutile sur le serveur car il s’agit d’un travail que nous avons arrêté d’écouter en mode frontal.

Le problème que j’essayais de résoudre (auquel d’autres pourraient s’adresser également) est que, lorsque l’utilisateur saisissait des informations dans un champ de saisie, je voulais lancer une demande de type de sensation Google Instant.

Pour éviter de lancer des requêtes inutiles et conserver la vivacité de l'interface, j'ai procédé comme suit:

var xhrQueue = [];
var xhrCount = 0;

$('#search_q').keyup(function(){

    xhrQueue.Push(xhrCount);

    setTimeout(function(){

        xhrCount = ++xhrCount;

        if (xhrCount === xhrQueue.length) {
            // Fire Your XHR //
        }

    }, 150);

});

Cela envoie essentiellement une demande toutes les 150ms (une variable que vous pouvez personnaliser pour vos propres besoins). Si vous ne parvenez pas à comprendre ce qui se passe exactement ici, connectez-vous xhrCount et xhrQueue à la console juste avant le bloc if.

12
brianrhea

Utilisez simplement ajax.abort () par exemple, vous pouvez abandonner toute demande ajax en attente avant d’en envoyer une autre comme celle-ci.

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

il n'y a pas de moyen fiable de le faire, et je ne l'essayerais même pas une fois la demande en mouvement; le seul moyen de réagir raisonnablement consiste à ignorer la réponse.

dans la plupart des cas, cela peut se produire dans des situations telles que: un utilisateur clique trop souvent sur un bouton déclenchant de nombreux XHR consécutifs; vous avez ici de nombreuses options: bloquer le bouton jusqu'à ce que XHR soit renvoyé, ou ne même pas déclencher un nouveau XHR pendant qu'un autre s'exécute. l'utilisateur de se pencher en arrière - ou de rejeter toute réponse XHR en attente mais la plus récente.

10
comeGetSome

Vous pouvez interrompre tout appel ajax continu en utilisant cette

<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>
8
Soubhagya Kumar

Le code suivant montre l’initiation et l’abandon d’une requête 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!" >
7
zloctb

J'ai eu le problème de polling et une fois la page fermée, le sondage a continué, donc dans mon cas, un utilisateur raterait une mise à jour car une valeur mysql était définie pour les 50 secondes suivantes après la fermeture de la page, alors que j'avais tué la requête ajax, En utilisant $ _SESSION pour définir une variable, elle ne se mettra pas à jour dans le sondage jusqu'à ce qu'elle soit terminée et qu'une nouvelle ait été commencée. Par conséquent, ce que j'ai fait a été une valeur dans ma base de données: 0 = offpage, alors que polling J'interroge cette ligne et renvoie false; quand il vaut 0, l'interrogation dans l'interrogation vous donnera évidemment les valeurs actuelles ...

J'espère que cela a aidé

5
Marcus

J'ai partagé une démo qui montre comment annuler une demande AJAX si les données ne sont pas renvoyées par le serveur dans un délai d'attente prédéfini.

HTML:

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

CODE 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);   
});
4
ganesh

Si xhr.abort(); provoque le rechargement de la page,

Ensuite, vous pouvez définir onreadystatechange avant l’abandon pour éviter:

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