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

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

Ответ 1

Вдохновленный aviv answer, я немного разобрался, и это то, что я придумал.
Я не уверен, что все это полезное в соответствии с комментариями в script и, конечно, будет работать только для браузеров с использованием собственного объекта 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
});

Ответ 2

ПРИМЕЧАНИЕ. Принятый ответ не дает фактического ответа, поскольку его вызывают слишком рано.

Вы можете сделать это, что в общем случае будет перехватывать любой AJAX в глобальном масштабе и не портить никакие обратные вызовы и т.д., Которые, возможно, были назначены любыми сторонними библиотеками 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

(Обратите внимание, это не работает <= IE8)

Ответ 3

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

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

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

Ответ 4

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

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

Код Psuedo:

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

Ответ 5

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

https://github.com/jpillora/xhook

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

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

Ответ 6

Используя ответ "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 );
    }
});

Ответ 7

В дополнение к 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 не завершались.

Ответ 8

JQuery...

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

Ответ 9

Ajax-hook - это lib с открытым исходным кодом для привязки глобального объекта 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])
  }

})