javascript 为页面上的所有 AJAX 请求添加“钩子”

tktrz96b  于 2023-05-27  发布在  Java
关注(0)|答案(9)|浏览(150)

我想知道是否有可能“挂钩”到每一个 AJAX 请求(无论是当它即将被发送,或对事件),并执行一个动作。在这一点上,我假设页面上还有其他第三方脚本。其中一些可能使用jQuery,而另一些则不使用。这可能吗?

2ledvvac

2ledvvac1#

**注意:接受的答案不会产生实际的响应,因为它被过早调用。

你可以这样做,这将一般拦截任何 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);
    };
})();

更多关于你可以在这里使用addEventListener API做什么的文档:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress
(Note这不起作用<= IE8)

guicsvcw

guicsvcw2#

受到aviv的回答的启发,我做了一点调查,这就是我的结论。

我不确定它是否有用根据脚本中的注解,当然只适用于使用本地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
});
xdyibdwo

xdyibdwo3#

既然你提到了jquery,我知道jquery提供了一个.ajaxSetup()方法,它设置了全局 AJAX 选项,包括像successerrorbeforeSend这样的事件触发器--这听起来像是你正在寻找的。

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

当然,你需要在你试图使用这个解决方案的任何页面上验证jQuery的可用性。

sirbozc5

sirbozc54#

我在Github上找到了一个很好的库,它可以很好地完成这项工作,你必须在任何其他js文件之前包含它
https://github.com/jpillora/xhook
下面是一个向任何传入响应添加HTTP标头的示例

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

mrwjdhj35#

使用“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 );
    }
});
nwsw7zdq

nwsw7zdq6#

做这件事有一个窍门。
在所有脚本运行之前,获取原始的XHMHttpReuqest对象并将其保存在不同的var中。然后覆盖原始XMLHttpRequest并通过您自己的对象将所有调用定向到它。
伪代码:

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

esyap4oy7#

除了meouw的答案之外,我还必须将代码注入到一个拦截XHR调用的iframe中,并使用上面的答案。然而,我不得不改变

XMLHttpRequest.prototype.send = function(){

收件人:

XMLHttpRequest.prototype.send = function(body)

我不得不改变

oldSend.apply(this, arguments);

收件人:

oldSend.call(this, body);

这是必要的,让它在IE9与 *IE8文档模式 * 工作。如果不进行此修改,则组件框架(Visual WebGUI)生成的一些回调将无法工作。更多信息在这些链接:

如果没有这些修改 AJAX 回发就不会终止。

cvxl0en2

cvxl0en28#

jquery...

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

ykejflvf9#

查看jquery ajax events。你可以这样做:

$(document).on("ajaxSend", function (e) {
    console.log("before request is sent");
}).on("ajaxComplete", function (e) {
    console.log("after success or error");
}).on("ajaxSuccess ", function (e) {
    console.log("on success");
}).on("ajaxError ", function (e) {
    console.log("on error");
});

相关问题