web-dev-qa-db-fra.com

Comment annuler / annuler une requête jQuery AJAX?

J'ai une demande AJAX qui sera faite toutes les 5 secondes. Mais le problème se situe avant la demande AJAX si la demande précédente n'est pas terminée, je dois abandonner 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);
);
236
user556673

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

XMLHttpRequest a une méthode abort , qui annule la demande, mais si la demande a déjà été envoyée au serveur, le serveur traitera la demande même si nous abandonnons la demande mais que 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);
);
347
Arun P Johny

Je sais que cela pourrait être un peu tard mais j'éprouve des problèmes similaires où appeler la méthode d'abandon n'a pas vraiment annulé la demande. Au lieu de cela, le navigateur attendait toujours une réponse qu’il n’utilisait jamais. ce code a résolu ce problème.

 try {
        xhr.onreadystatechange = null;
        xhr.abort();
} catch (e) {}
5
Lyon

Lorsque vous faites une demande à un serveur, demandez-lui de vérifier si une progression n'est pas nulle (ou d'extraire ces données) en premier. S'il récupère des données, abandonnez la requête 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;
        }
    });
}
2
Taz

Pourquoi devriez-vous abandonner la demande?

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

Vous ne devez pas abandonner la demande si le paramètre transmis avec la demande ne change pas. Par exemple: - la requête est destinée à récupérer les données de notification. Dans de telles situations, l’approche de Nice consiste à définir une nouvelle demande uniquement 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);

);
1
Habeeb Perwad

Vous pouvez utiliser jquery-validate.js. Voici l'extrait de code 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);
    };
}

Il vous suffit donc de définir le mode du paramètre avec abandon lorsque vous faites une demande ajax.

Réf.: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js

0
zawhtut

jQuery: Utilisez ceci comme point de départ - comme source d’inspiration. Je l'ai résolu comme ceci: (ce n'est pas une solution parfaite, il avorte juste la dernière instance et 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.
0
BananaAcid

Créez une fonction pour appeler votre API. Dans cette fonction, nous définissons la demande callApiRequest = $.get(... - même s’il s’agit d’une définition de variable, la demande est appelée immédiatement, mais nous avons maintenant la demande définie en tant que variable. Avant l'appel de la demande, nous vérifions si notre variable est définie typeof(callApiRequest) != 'undefined' et également si elle est en attente suggestCategoryRequest.state() == 'pending' - si les deux sont vraies, nous .abort() la demande qui empêchera l'exécution du rappel de succès.

// 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 peut ne pas prendre en charge l'abandon de la demande (que se passe-t-il si l'API exécute déjà du code?), Mais le rappel javascript ne se déclenchera pas. Ceci est utile lorsque, par exemple, vous fournissez des suggestions d'entrée à un utilisateur, telles que la saisie de hashtags.

Vous pouvez étendre davantage cette fonction en ajoutant la définition du rappel d'erreur - que devrait-il se passer si la demande est abandonnée?.

Le cas d'utilisation courant pour cet extrait de code serait une entrée de texte qui se déclenche lors de l'événement keypress. Vous pouvez utiliser un délai d’expiration pour empêcher l’envoi (de certaines) des demandes qui devront annuler .abort().

0
mate.gwozdz