126 votes

Ajouter un "hook" à toutes les requêtes AJAX sur une page

Je voudrais savoir s'il est possible de "crocheter" dans chaque demande AJAX (soit avant qu'elle ne soit envoyée, soit lors d'événements) et d'effectuer une action. À ce stade, je suppose qu'il y a d'autres scripts tiers sur la page. Certains d'entre eux pourraient utiliser jQuery, tandis que d'autres non. Est-ce possible ?

178voto

John Culviner Points 4878

REMARQUE : La réponse acceptée ne produit pas la réponse réelle car elle est appelée trop tôt.

Vous pouvez faire ceci qui interceptera de manière générique tout AJAX de manière globale et ne perturbera pas les rappels etc. qui ont peut-être été assignés par des bibliothèques AJAX tierces.

(function() {
    var origOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
        console.log('requête commencée!');
        this.addEventListener('load', function() {
            console.log('requête terminée!');
            console.log(this.readyState); // sera toujours 4 (l'ajax est complété avec succès)
            console.log(this.responseText); // quelle que soit la réponse
        });
        origOpen.apply(this, arguments);
    };
})();

Quelques autres documents sur ce que vous pouvez faire ici avec l'API addEventListener :

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress

(Remarque : cela ne fonctionne pas avec <= IE8)

122voto

meouw Points 21368

Inpiré par la réponse d'Aviv, j'ai fait un peu de recherche et voici ce que j'ai trouvé.
Je ne suis pas sûr que cela soit très utile comme le disent les commentaires dans le script et bien sûr ne fonctionnera que pour les navigateurs utilisant un objet XMLHttpRequest natif.
Je pense que cela fonctionnera si des bibliothèques javascript sont utilisées car elles utiliseront l'objet natif si possible.

function addXMLRequestCallback(callback){
    var oldSend, i;
    if( XMLHttpRequest.callbacks ) {
        // nous avons déjà remplacé send() alors ajoutons simplement le callback
        XMLHttpRequest.callbacks.push( callback );
    } else {
        // créer une file d'attente de callback
        XMLHttpRequest.callbacks = [callback];
        // stocker le send() natif
        oldSend = XMLHttpRequest.prototype.send;
        // remplacer le send() natif
        XMLHttpRequest.prototype.send = function(){
            // traiter la file d'attente de callback
            // l'instance xhr est passée à chaque callback mais semble assez inutile
            // vous ne pouvez pas dire quelle est sa destination ni appeler abort() sans erreur
            // donc vraiment seulement bon pour enregistrer qu'une requête a eu lieu
            // je pourrais me tromper, j'espère que oui...
            // EDIT: je suppose que vous pourriez remplacer le gestionnaire onreadystatechange cependant
            for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
                XMLHttpRequest.callbacks[i]( this );
            }
            // appeler le send() natif
            oldSend.apply(this, arguments);
        }
    }
}

// par exemple
addXMLRequestCallback( function( xhr ) {
    console.log( xhr.responseText ); // (une chaîne vide)
});
addXMLRequestCallback( function( xhr ) {
    console.dir( xhr ); // jetez un œil s'il y a quelque chose d'utile ici
});

22voto

jondavidjohn Points 28769

Depuis que vous mentionnez jQuery, je sais que jQuery propose une méthode .ajaxSetup() qui définit des options ajax globales comprenant les déclencheurs d'événements tels que success, error et beforeSend - ce qui semble être ce que vous recherchez.

$.ajaxSetup({
    beforeSend: function() {
        //faire des choses avant que la requête ne soit lancée
    }
});

Bien sûr, vous devriez vérifier la disponibilité de jQuery sur n'importe quelle page sur laquelle vous essayez d'utiliser cette solution.

10voto

Mohamed Selim Points 1522

J'ai trouvé une bonne bibliothèque sur Github qui fait bien le travail, vous devez l'inclure avant tous les autres fichiers js

https://github.com/jpillora/xhook

Voici un exemple qui ajoute un en-tête http à toute réponse entrante

xhook.after(function(request, response) {
  response.headers['Foo'] = 'Bar';
});

8voto

aviv Points 1333

Il y a un truc pour le faire.

Avant de lancer tous les scripts, prenez l'objet XHMHttpReuqest original et sauvegardez-le dans une variable différente. Ensuite, remplacez XMLHttpRequest original et redirigez tous les appels vers votre propre objet.

Code pseudo :

 var savd = XMLHttpRequest;
XMLHttpRequest.prototype = function() {
    this.init = function() {
    }; // votre code
    etc' 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