41 votes

JavaScript : Détecter les requêtes AJAX

Existe-t-il un moyen de détecter les appels AJAX globaux (en particulier les réponses) sur une page web avec du JavaScript générique (pas avec des frameworks) ?

J'ai déjà examiné la question " JavaScript détecte un événement AJAX "J'ai essayé Parcheando dans le code de la réponse acceptée dans mon application, mais cela n'a pas fonctionné. Je n'ai jamais rien fait avec AJAX avant non plus, donc, je n'en sais pas assez pour le modifier pour qu'il fonctionne.

Je n'ai pas besoin de quelque chose de sophistiqué, j'ai juste besoin de détecter toutes les réponses AJAX (spécifiques, en fait, mais je devrais d'abord les détecter toutes et partir de là) et de les patcher dans une instruction IF pour les utiliser. Donc, en fin de compte, je voudrais quelque chose comme :

if (ajax.response == "certainResponseType"){
    //Code
}

par exemple.

Mise à jour : Il semble que je doive préciser que je n'essaie pas d'envoyer une requête - je développe un script de contenu et j'ai besoin de pouvoir détecter les requêtes AJAX de la page web (et non les miennes), afin de pouvoir exécuter une fonction lorsqu'une réponse est détectée.

48voto

Omn Points 348

Voici du code (testé en le collant dans la console de Chrome 31.0.1650.63) pour attraper et enregistrer ou traiter les requêtes ajax et leurs réponses :

(function() {
    var proxied = window.XMLHttpRequest.prototype.send;
    window.XMLHttpRequest.prototype.send = function() {
        console.log( arguments );
        //Here is where you can add any code to process the request. 
        //If you want to pass the Ajax request object, pass the 'pointer' below
        var pointer = this
        var intervalId = window.setInterval(function(){
                if(pointer.readyState != 4){
                        return;
                }
                console.log( pointer.responseText );
                //Here is where you can add any code to process the response.
                //If you want to pass the Ajax request object, pass the 'pointer' below
                clearInterval(intervalId);

        }, 1);//I found a delay of 1 to be sufficient, modify it as you need.
        return proxied.apply(this, [].slice.call(arguments));
    };

})();

Ce code résout le problème susmentionné avec la réponse acceptée :

Notez que cela peut ne pas fonctionner si vous utilisez des frameworks (comme jQuery), ils peuvent surcharger onreadystatechange après avoir appelé send (je pense que c'est le cas de jQuery le fait). Ou ils peuvent surcharger la méthode send (mais c'est peu probable). Il s'agit donc d'une solution partielle.

Parce qu'il ne s'appuie pas sur le fait que le callback "onreadystatechange" reste inchangé, mais qu'il surveille l'état "readyState" lui-même.

J'ai adapté la réponse à partir d'ici : https://stackoverflow.com/a/7778218/1153227

36voto

mmguy Points 361

Essaie de le faire. Détecte les réponses Ajax, puis j'ai ajouté une conditionnelle utilisant les propriétés XMLHttpRequest readyState & status pour exécuter la fonction if response status = OK

var oldXHR = window.XMLHttpRequest;

function newXHR() {
    var realXHR = new oldXHR();
    realXHR.addEventListener("readystatechange", function() {
        if(realXHR.readyState==4 && realXHR.status==200){
            afterAjaxComplete() //run your code here
        }
    }, false);
    return realXHR;
}
window.XMLHttpRequest = newXHR;

Modifié à partir de : Surveiller tous les événements JavaScript dans la console du navigateur

21voto

freakish Points 20067

Cela peut s'avérer un peu délicat. Que pensez-vous de ceci ?

var _send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function() {

    /* Wrap onreadystaechange callback */
    var callback = this.onreadystatechange;
    this.onreadystatechange = function() {             
         if (this.readyState == 4) {
             /* We are in response; do something,
                like logging or anything you want */
         }
         callback.apply(this, arguments);
    }

    _send.apply(this, arguments);
}

Je ne l'ai pas testée, mais elle semble plus ou moins bien fonctionner.

Notez que cela peut ne pas fonctionner si vous utilisez des frameworks (comme jQuery), parce qu'ils peuvent surcharger la fonction onreadystatechange après avoir appelé send (je pense que c'est le cas de jQuery). Ou ils peuvent remplacer send (mais c'est peu probable). Il s'agit donc d'une solution partielle.

EDITAR: Aujourd'hui (début 2018), cela devient plus compliqué avec la nouvelle API de recherche . Mondial fetch doit également être remplacée de la même manière.

10voto

Dai Points 24530

Une réponse moderne (à partir d'avril 2021) à la question est d'utiliser PerformanceObserver qui vous permet d'observer à la fois XMLHttpRequest demandes et fetch() demandes :

  • Détecter une requête API sur une page web en JavaScript
  • Détecter les requêtes ajax à partir du HTML brut

    <!-- Place this at the top of your page's <head>: --> <script type="text/javascript"> var myRequestLog = []; // Using var (instead of let or const) so it creates an implicit property on the (global) window object so you can easily access this log from anywhere just by using window.myRequestLog[...]. function onRequestsObserved( batch ) { myRequestLog.push( ...batch.getEntries() ); } var requestObserver = new PerformanceObserver( onRequestsObserved ); requestObserver.observe( { type: 'resource' /, buffered: true / } ); </script>

J'utilise l'extrait ci-dessus dans mes pages pour enregistrer les demandes afin de pouvoir les rapporter au vaisseau mère dans mon système global. window.addEventListenr('error', ... ) rappel.


  • En batch.getEntries() renvoie un tableau de DOM PerformanceResourceTiming (car nous n'écoutons que les objets type: 'resource' sinon il renverrait un tableau d'objets de types différents).
  • Chaque PerformanceResourceTiming possède des propriétés utiles telles que :
    • En initiatorType peut être :
      • Un nom d'élément HTML (nom de balise) si la demande a été causée par un élément :
        • 'link' - La demande émane d'un <link> dans la page.
        • 'script' - La demande consistait à charger un <script> .
        • 'img' - La demande consistait à charger un <img /> élément.
        • etc.
      • 'xmlhttprequest' - La demande a été causée par une XMLHttpRequest invocation.
      • 'fetch' - La demande a été causée par une fetch() appel.
    • name - L'URI de la ressource/requête. (En cas de redirection, je ne sais pas s'il s'agit de l'URI de la demande initiale ou de l'URI de la demande finale).
    • startTime : Attention : il s'agit en fait du temps écoulé depuis PerformanceObserver.observe() a été appelé lorsque la demande a été lancée.
    • duration : Attention : il s'agit en fait du temps écoulé depuis PerformanceObserver.observe() a été appelée lorsque la demande a été satisfaite : ce n'est pas seulement la durée de la demande . Pour obtenir la mention " réel "durée vous devez soustraire startTime de duration .
    • transferSize : le nombre d'octets de la réponse.

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