Добавьте "крючок" ко всем запросам AJAX на странице



Я хотел бы знать, можно ли "зацепить" каждый запрос AJAX (либо по мере его отправки, либо по событиям) и выполнить действие. На данный момент я предполагаю, что есть и другие сторонние скрипты на странице. Некоторые из них могут использовать jQuery, а другие-нет. Это возможно?

617   9  

9 ответов:

вдохновленный - Авива, Я сделал небольшое расследование, и это то, что я придумал.
Я не уверен, что это все, что полезно согласно комментариям в скрипте и конечно будет работать только для браузеров, использующих собственный объект XMLHttpRequest.
Я думаю, что это будет работать, если библиотеки javascript используются, поскольку они будут использовать собственный объект, если это возможно.

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

Если вам не нужно поддерживать любой Аякс глобально и не запороть любые обратные вызовы и т. д. это может быть назначено любыми сторонними библиотеками AJAX. Принятый ответ не дает фактического ответа, потому что он вызывается слишком рано.

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

еще несколько документов о том, что вы можете сделать здесь с помощью API addEventListener здесь:

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

поскольку вы упомянули jquery, я знаю, что jquery предлагает .ajaxSetup() метод, который устанавливает глобальные параметры ajax, которые включают триггеры событий, такие как success,error и beforeSend - что это звучит как то, что вы ищете.

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

конечно, вам нужно будет проверить доступность jQuery на любой странице, на которой вы пытаетесь использовать это решение.

есть трюк, чтобы сделать это.

перед запуском всех сценариев возьмите исходный объект XHMHttpReuqest и сохраните его в другом var. Затем переопределите исходный XMLHttpRequest и направьте все вызовы к нему через свой собственный объект.

код Psuedo:

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

Я нашел хорошую библиотеку на Github, которая хорошо справляется с этой работой, вы должны включить ее перед любыми другими файлами js

https://github.com/jpillora/xhook

вот пример, который добавляет заголовок http к любому входящему ответу

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

используя ответ "meouw" я предлагаю использовать следующее решение, если вы хотите увидеть результаты запроса

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

jquery...

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

в дополнение к ответу meouw мне пришлось ввести код в iframe, который перехватывает вызовы XHR, и использовал приведенный выше ответ. Однако, мне пришлось изменить

XMLHttpRequest.prototype.send = function(){

To:

XMLHttpRequest.prototype.send = function(arguments)

и мне пришлось изменить

oldSend.apply(this, arguments);

To:

oldSend.call(this, arguments);

Это было необходимо, чтобы заставить его работать в IE9 с режим документа IE8. Если это изменение не было сделано, некоторые обратные вызовы, созданные платформой компонентов (Visual WebGUI), не работали. Более подробная информация по этим ссылкам:

Ajax-hook - это библиотека с открытым исходным кодом для подключения глобального объекта XMLHttpRequest и изменения запроса и ответа Ajax по умолчанию . github:https://github.com/wendux/Ajax-hook , например:

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

})

Comments

    Ничего не найдено.