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

j'aimerais savoir s'il est possible de" hook " dans chaque requête AJAX (que ce soit sur le point d'être envoyée, ou sur des événements) et d'effectuer une action. À ce stade, je suppose qu'il y a d'Autres scripts tiers sur la page. Certains peuvent utiliser jQuery, tandis que d'autres ne le font pas. Est-ce possible?

79
demandé sur Yuliy 2011-03-05 10:04:21

9 réponses

inspiré par réponse d'aviv , j'ai fait une petite enquête et c'est ce que j'ai trouvé.

Je ne suis pas sûr que ce soit tout ce que utile selon les commentaires dans le script et bien sûr ne fonctionnera que pour les navigateurs utilisant un objet xmltprequest natif .

Je pense que cela fonctionnera si les bibliothèques javascript sont utilisées car elles utiliseront l'objet natif si possible.

function addXMLRequestCallback(callback){
    var oldSend, i;
    if( XMLHttpRequest.callbacks ) {
        // we've already overridden send() so just add the callback
        XMLHttpRequest.callbacks.push( callback );
    } else {
        // create a callback queue
        XMLHttpRequest.callbacks = [callback];
        // store the native send()
        oldSend = XMLHttpRequest.prototype.send;
        // override the native send()
        XMLHttpRequest.prototype.send = function(){
            // process the callback queue
            // the xhr instance is passed into each callback but seems pretty useless
            // you can't tell what its destination is or call abort() without an error
            // so only really good for logging that a request has happened
            // I could be wrong, I hope so...
            // EDIT: I suppose you could override the onreadystatechange handler though
            for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
                XMLHttpRequest.callbacks[i]( this );
            }
            // call the native send()
            oldSend.apply(this, arguments);
        }
    }
}

// e.g.
addXMLRequestCallback( function( xhr ) {
    console.log( xhr.responseText ); // (an empty string)
});
addXMLRequestCallback( function( xhr ) {
    console.dir( xhr ); // have a look if there is anything useful here
});
95
répondu meouw 2017-05-23 11:47:14

si vous n'avez pas à supporter <= IE8, vous pouvez faire cela qui interceptera de manière générique n'importe quel AJAX globalement et ne ratera aucun callbacks etc. qui peut-être ont été assignés par des bibliothèques AJAX tierces. La réponse acceptée ne donne pas la réponse réelle parce qu'elle est appelée trop tôt.

(function() {
    var origOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
        console.log('request started!');
        this.addEventListener('load', function() {
            console.log('request completed!');
            console.log(this.readyState); //will always be 4 (ajax is completed successfully)
            console.log(this.responseText); //whatever the response was
        });
        origOpen.apply(this, arguments);
    };
})();

un peu plus de docs de ce que vous pouvez faire ici avec l'API addEventListener ici:

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

80
répondu John Culviner 2015-01-19 06:36:03

puisque vous mentionnez jquery, je sais que jquery offre une méthode .ajaxSetup() qui définit des options ajax globales qui incluent les déclencheurs d'événements comme success , error , et beforeSend - qui est ce qui ressemble à ce que vous recherchez.

$.ajaxSetup({
    beforeSend: function() {
        //do stuff before request fires
    }
});

bien sûr, vous auriez besoin de vérifier la disponibilité de jQuery sur toute page que vous essayez d'utiliser cette solution sur.

20
répondu jondavidjohn 2011-03-05 07:10:32

il y a un truc pour le faire.

avant d'exécuter tous les scripts, prenez L'objet XHMHttpReuqest original et sauvegardez-le dans un var différent. Ensuite, outrepassez la requête XMLHttpRequest originale et dirigez tous les appels vers celle-ci via votre propre objet.

code Psuedo:

 var savd = XMLHttpRequest;
 XMLHttpRequest.prototype = function() {
         this.init = function() {
         }; // your code
         etc' etc'
 };
9
répondu aviv 2011-03-05 07:09:01

j'ai trouvé une bonne bibliothèque sur Github qui fait le travail bien, 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 à n'importe quelle réponse entrante

xhook.after(function(request, response) {
  response.headers['Foo'] = 'Bar';
});
5
répondu Mohamed Selim 2016-09-08 09:35:09

en utilisant la réponse de "meouw" je suggère d'utiliser la solution suivante si vous voulez voir les résultats de la demande

function addXMLRequestCallback(callback) {
    var oldSend, i;
    if( XMLHttpRequest.callbacks ) {
        // we've already overridden send() so just add the callback
        XMLHttpRequest.callbacks.push( callback );
    } else {
        // create a callback queue
        XMLHttpRequest.callbacks = [callback];
        // store the native send()
        oldSend = XMLHttpRequest.prototype.send;
        // override the native send()
        XMLHttpRequest.prototype.send = function() {
            // call the native send()
            oldSend.apply(this, arguments);

            this.onreadystatechange = function ( progress ) {
               for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
                    XMLHttpRequest.callbacks[i]( progress );
                }
            };       
        }
    }
}

addXMLRequestCallback( function( progress ) {
    if (typeof progress.srcElement.responseText != 'undefined' &&                        progress.srcElement.responseText != '') {
        console.log( progress.srcElement.responseText.length );
    }
});
4
répondu heroin 2013-11-12 11:34:53

jquery...

<script>
   $(document).ajaxSuccess(
        function(event, xhr, settings){ 
          alert(xhr.responseText);
        }
   );
</script>
3
répondu Vladimir Miroshnichenko 2013-09-12 19:14:31

en plus de la réponse de meouw, j'ai dû injecter du code dans une iframe qui intercepte les appels XHR, et j'ai utilisé la réponse ci-dessus. Cependant, j'ai dû changer

XMLHttpRequest.prototype.send = function(){

à:

XMLHttpRequest.prototype.send = function(arguments)

et j'ai dû changer

oldSend.apply(this, arguments);

à:

oldSend.call(this, arguments);

cela était nécessaire pour obtenir le fonctionnement dans IE9 avec mode de document IE8 . Si cette modification n'a pas été faite, certains les rappels générés par le framework component (Visual WebGUI) n'ont pas fonctionné. Plus d'informations sur ces liens:

sans ces modifications AJAX postbacks n'a pas pris fin.

3
répondu WC1 2014-10-15 14:08:28

Ajax-hook est un lib open source pour hook global XMLHttpRequest object, et change la requête Ajax par défaut et la réponse . github: https://github.com/wendux/Ajax-hook exemple:

hookAjax({

  //hook callbacks
  onreadystatechange:function(xhr){
   console.log("onreadystatechange called: %O",xhr)
  },

  onload:function(xhr){
   console.log("onload called: %O",xhr)
  },

  //hook function
  open:function(arg,xhr){
   console.log("open called: method:%s,url:%s,async:%s",arg[0],arg[1],arg[2])
  }

})
1
répondu wendu 2018-03-08 11:16:54