Domanda Aggiungi un "gancio" a tutte le richieste AJAX su una pagina


Mi piacerebbe sapere se è possibile "agganciarsi" ad ogni singola richiesta AJAX (o mentre sta per essere inviata, o sugli eventi) ed eseguire un'azione. A questo punto presumo che ci siano altri script di terze parti nella pagina. Alcuni di questi potrebbero usare jQuery, mentre altri no. È possibile?


78
2018-03-05 07:04


origine


risposte:


Ispirato da la risposta di aviv, Ho fatto un po 'di ricerche e questo è quello che mi è venuto in mente.
Non sono sicuro che sia così utile come da commenti nella sceneggiatura e, naturalmente funzionerà solo per i browser che utilizzano un oggetto XMLHttpRequest nativo.
Penso che funzionerà se le librerie javascript sono in uso poiché useranno l'oggetto nativo se possibile.

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
});

92
2018-03-05 09:47



Se non devi supportare <= IE8 puoi farlo in modo generico qualunque AJAX a livello globale e non rovinare eventuali richiami, ecc. Che potrebbero essere stati assegnati da librerie AJAX di terze parti. La risposta accettata non produce la risposta effettiva perché viene chiamata troppo presto.

(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);
    };
})();

Alcuni altri documenti su ciò che puoi fare qui con l'API addEventListener qui:

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


74
2017-12-08 17:33



Dato che parli di jquery, so che jquery offre a .ajaxSetup() metodo che imposta opzioni Ajax globali che includono i trigger di eventi come success, error, e beforeSend - che è quello che sembra quello che stai cercando.

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

ovviamente è necessario verificare la disponibilità di jQuery su qualsiasi pagina in cui si tenta di utilizzare questa soluzione.


19
2018-03-05 07:10



C'è un trucco per farlo.

Prima di eseguire tutti gli script, prendi l'oggetto XHMHttpReuqest originale e salvalo in una var diversa. Quindi sostituisci l'originale XMLHttpRequest e indirizza tutte le chiamate ad esso tramite il tuo oggetto.

Codice Psuedo:

 var savd = XMLHttpRequest;
 XMLHttpRequest.prototype = function() {
         this.init = function() {
         }; // your code
         etc' etc'
 };

9
2018-03-05 07:09



Usando la risposta di "meouw" suggerisco di usare la seguente soluzione se vuoi vedere i risultati della richiesta

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
2017-11-12 11:34



Ho trovato una buona libreria su Github che fa bene il lavoro, devi includerlo prima di ogni altro file js

https://github.com/jpillora/xhook

ecco un esempio che aggiunge un'intestazione http a qualsiasi risposta in arrivo

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

4
2017-09-08 09:35



jquery ...

<script>
   $(document).ajaxSuccess(
        function(event, xhr, settings){ 
          alert(xhr.responseText);
        }
   );
</script>

3
2017-09-12 19:14



Oltre alla risposta di meouw, ho dovuto inserire il codice in un iframe che intercetta le chiamate XHR e ho usato la risposta di cui sopra. Tuttavia, ho dovuto cambiare

XMLHttpRequest.prototype.send = function(){

A:

XMLHttpRequest.prototype.send = function(arguments)

E ho dovuto cambiare

oldSend.apply(this, arguments);

A:

oldSend.call(this, arguments);

Questo era necessario per farlo funzionare in IE9 con Modalità documento IE8. Se questa modifica non è stata apportata, alcuni richiami generati dal framework del componente (Visual WebGUI) non hanno funzionato. Maggiori informazioni su questi collegamenti:

Senza queste modifiche i postback AJAX non si sono conclusi.


3
2017-12-08 14:49



Ajax-hook è una libreria open source che aggancia l'oggetto XMLHttpRequest globale e modifica la richiesta e la risposta Ajax predefinite. GitHub:https://github.com/wendux/Ajax-hook, per esempio:

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
2018-03-08 11:10