259 votes

Comment annuler/abandonner une requête AJAX jQuery ?

J'ai une requête AJAX qui sera effectuée toutes les 5 secondes. Mais le problème est qu'avant la requête AJAX, si la requête précédente n'est pas terminée, je dois abandonner cette requête et en faire une nouvelle.

Mon code est quelque chose comme ceci, comment résoudre ce problème ?

$(document).ready(
    var fn = function(){
        $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);

11 votes

8 votes

Votre question stipule que la requête doit avoir lieu toutes les 5 secondes, mais le code utilise 500 ms = 0,5 s.

373voto

Arun P Johny Points 151748

La méthode jquery ajax renvoie un XMLHttpRequest objet. Vous pouvez utiliser cet objet pour annuler la demande.

Le XMLHttpRequest possède une fonction [abandonner](https://xhr.spec.whatwg.org/#the-abort()-method) qui annule la demande, mais si la demande a déjà été envoyée au serveur, la méthode le serveur traitera la demande même si nous abandonnons la demande, le client n'attendra pas/ne traitera pas la réponse.

L'objet xhr contient également un readyState qui contient l'état de la demande (UNSENT-0, OPENED-1, HEADERS_RECEIVED-2, LOADING-3 et DONE-4). Nous pouvons l'utiliser pour vérifier si la demande précédente a été complétée.

$(document).ready(
    var xhr;

    var fn = function(){
        if(xhr && xhr.readyState != 4){
            xhr.abort();
        }
        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);

61 votes

@romkyns The differences is the property readystate ci-dessus et readyState ci-dessous, le caractère s est en majuscule dans jQuery 1.5

0 votes

Je me demandais ce qui se passe si le readyState est "LOADING-3" et que nous abandonnons ? Les données sont envoyées au serveur, et elles sont traitées ou non. Nous ne le saurons pas... :S

7 votes

Entre-temps, je pense que la vérification de readyState est inutile, puisqu'elle est différée et qu'une fois résolue ou rejetée, elle n'exécutera pas les autres. Donc if (xhr) xhr.abort(); fonctionnera aussi très bien.

9voto

Taz Points 39

Lorsque vous faites une demande à un serveur, demandez-lui de vérifier d'abord si une progression n'est pas nulle (ou de récupérer ces données). S'il récupère des données, abandonne la requête précédente et lance la nouvelle.

var progress = null

function fn () {    
    if (progress) {
        progress.abort();
    }
    progress = $.ajax('ajax/progress.ftl', {
        success: function(data) {
            //do something
            progress = null;
        }
    });
}

5voto

Joecoder001 Points 30

Il suffit d'utiliser ajax.abort(). Par exemple, vous pouvez interrompre toute requête ajax en cours avant d'en envoyer une autre, comme suit

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

1voto

HabeebPerwad Points 2081

Pourquoi devriez-vous interrompre la demande ?

Si chaque demande prend plus de cinq secondes, que se passera-t-il ?

Vous ne devez pas interrompre la demande si le paramètre transmis avec la demande ne change pas. Par exemple, la demande vise à récupérer les données de notification. Dans de telles situations, la bonne approche est de définir une nouvelle demande seulement après avoir complété la demande Ajax précédente.

$(document).ready(

    var fn = function(){

        $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            },

            complete: function(){setTimeout(fn, 500);}
        });
    };

     var interval = setTimeout(fn, 500);

);

6 votes

C'est une mauvaise idée. Lorsque vous lancez un nouvel appel, vous ne voulez pas que l'événement complet de l'appel précédent soit déclenché. Vous pourriez obtenir des résultats très étranges avec cette approche.

1voto

BananaAcid Points 279

JQuery : Utilisez ceci comme point de départ - comme inspiration. J'ai résolu le problème de la façon suivante : (ce n'est pas une solution parfaite, elle abandonne juste la dernière instance et c'est du code WIP)

var singleAjax = function singleAjax_constructor(url, params) {
    // remember last jQuery's get request
    if (this.lastInstance) {
        this.lastInstance.abort();  // triggers .always() and .fail()
        this.lastInstance = false;
    }

    // how to use Deferred : http://api.jquery.com/category/deferred-object/
    var $def = new $.Deferred();

    // pass the deferrer's request handlers into the get response handlers
    this.lastInstance = $.get(url, params)
        .fail($def.reject)         // triggers .always() and .fail()
        .success($def.resolve);    // triggers .always() and .done()

    // return the deferrer's "control object", the promise object
    return $def.promise();
}

// initiate first call
singleAjax('/ajax.php', {a: 1, b: 2})
    .always(function(a,b,c) {console && console.log(a,b,c);});

// second call kills first one
singleAjax('/ajax.php', {a: 1, b: 2})
    .always(function(a,b,c) {console && console.log(a,b,c);});
    // here you might use .always() .fail() .success() etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X