Comment annuler / annuler une demande jQuery AJAX?

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

mon code est quelque chose comme ça, 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);
);
233
demandé sur informatik01 2010-12-29 06:04:44

8 réponses

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

la XMLHttpRequest a une méthode abort , qui annule la requête, mais si la requête a déjà été envoyée au serveur alors le serveur traitera la requête même si nous annulons la requête mais le client n'attendra pas/ne traitera pas la réponse.

le l'objet xhr contient également un readyState qui contient l'état de la requête(UNSENT-0, Open-1, HEADERS_RECEIVED-2, LOADING-3 et DONE-4). nous pouvons l'utiliser pour vérifier si la demande précédente a été terminé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);
);
342
répondu Arun P Johny 2016-08-10 22:15:09

je sais que cela pourrait être un peu tard, mais je fais l'expérience de problèmes similaires où appeler la méthode d'abandon n'a pas vraiment avorté la demande. au lieu de cela, le navigateur attendait toujours une réponse qu'il n'utilise jamais. ce code a résolu ce problème.

 try {
        xhr.onreadystatechange = null;
        xhr.abort();
} catch (e) {}
5
répondu Lyon 2015-01-31 22:44:43

Pourquoi devrais-tu annuler la demande?

si chaque requête prend plus de cinq secondes, que se passera-t-il?

vous ne devez pas annuler la requête si le paramètre passant avec la requête ne change pas. eg:- la requête est pour extraire les données de notification. Dans de telles situations, l'approche de nice consiste à définir une nouvelle requête seulement après avoir complété la requête 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);

);
3
répondu Habeeb Perwad 2014-04-07 09:18:40

Lorsque vous faites une requête à un serveur, vérifier pour voir si un cours n'est pas null (ou extraction des données). S'il s'agit de récupérer des données, annulez la demande précédente et lancez la nouvelle.

var progress = null

function fn () {    
    if (progress) {
        progress.abort();
    }
    progress = $.ajax('ajax/progress.ftl', {
        success: function(data) {
            //do something
            progress = null;
        }
    });
}
1
répondu Taz 2017-11-28 12:11:27

jQuery: Utilisez ceci comme point de départ - comme source d'inspiration. Je l'ai résolu comme ça: (ce n'est pas une solution parfaite, c'est juste abandonne la dernière instance et est WIP code)

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.
0
répondu BananaAcid 2014-04-29 00:58:49

Vous pouvez utiliser jquery-valider.js . Voici le code extrait de jQuery-validate.js.

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()

var pendingRequests = {},
    ajax;
// Use a prefilter if available (1.5+)
if ( $.ajaxPrefilter ) {
    $.ajaxPrefilter(function( settings, _, xhr ) {
        var port = settings.port;
        if ( settings.mode === "abort" ) {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            pendingRequests[port] = xhr;
        }
    });
} else {
    // Proxy ajax
    ajax = $.ajax;
    $.ajax = function( settings ) {
        var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
            port = ( "port" in settings ? settings : $.ajaxSettings ).port;
        if ( mode === "abort" ) {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            pendingRequests[port] = ajax.apply(this, arguments);
            return pendingRequests[port];
        }
        return ajax.apply(this, arguments);
    };
}

de sorte que vous avez juste besoin de définir le paramètre mode à avorter quand vous faites une requête ajax.

Ref: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js

0
répondu zawhtut 2015-10-15 08:58:23

créez une fonction pour appeler votre API. Dans cette fonction nous définissons la requête callApiRequest = $.get(... - même si c'est une définition d'une variable, la requête est appelée immédiatement, mais maintenant nous avons la requête définie comme une variable. Avant que la requête ne soit appelée, nous vérifions si notre variable est définie typeof(callApiRequest) != 'undefined' et aussi si elle est en attente suggestCategoryRequest.state() == 'pending' - si les deux sont vraies, nous vérifions .abort() la requête qui empêchera le succès du callback de s'exécuter.

// We need to wrap the call in a function
callApi = function () {

    //check if request is defined, and status pending
    if (typeof(callApiRequest) != 'undefined'
        && suggestCategoryRequest.state() == 'pending') {

        //abort request
        callApiRequest.abort()

    }

    //define and make request
    callApiRequest = $.get("https://example.com", function (data) {

        data = JSON.parse(data); //optional (for JSON data format)
        //success callback

    });
}

votre serveur / API pourrait ne pas supporter d'annuler la requête (et si L'API avait déjà exécuté du code?), mais le rappel javascript ne fonctionnera pas. Ceci est utile lorsque, par exemple, vous donnez des suggestions d'entrées à un utilisateur, telles que des hashtags input.

vous pouvez étendre cette fonction en ajoutant la définition de callback d'erreur - ce qui doit se passer si la requête a été annulée.

cas d'usage courant pour cet extrait serait une entrée de texte qui incendies lors de l'événement keypress . Vous pouvez utiliser un timeout, pour empêcher l'envoi (de certaines) requêtes que vous devrez annuler .abort() .

0
répondu mate.gwozdz 2018-09-07 20:01:32

vous devriez également vérifier pour readyState 0. Parce que quand vous utilisez xhr.abort () cette fonction définit readyState à 0 dans cet objet, et votre si check sera toujours true - readyState != 4

$(document).ready(
    var xhr;

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

    var interval = setInterval(fn, 500);
); 
-7
répondu programmer 2013-10-24 08:10:58