41

有没有办法用通用 JavaScript(不是框架)在网页上检测全局 AJAX 调用(特别是响应)?

我已经在 StackOverflow 上查看了“ JavaScript 检测 AJAX 事件”问题,并尝试将已接受答案的代码修补到我的应用程序中,但没有成功。在此之前我从未对 AJAX 做过任何事情,所以我不知道如何修改它以使其正常工作。

我不需要任何花哨的东西,我只需要检测所有(实际上是具体的,但我必须先检测所有并从那里开始)AJAX 响应并将它们修补到 IF 语句中以供使用。所以,最终,我想要这样的东西:

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

, 例如。

更新: 似乎我应该澄清一下我不是在尝试发送请求 - 我正在开发一个内容脚本,我需要能够检测网页的 AJAX 请求(不是我自己的),所以我可以执行检测到响应时起作用。

4

4 回答 4

44

下面是一些代码(通过粘贴到 Chrome 31.0.1650.63 的控制台进行测试)用于捕获和记录或以其他方式处理 ajax 请求及其响应:

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


})();

此代码通过接受的答案解决了上述问题:

请注意,如果您使用框架(如 jQuery),它可能不起作用,因为它们可能会在调用 send 后覆盖 onreadystatechange(我认为 jQuery 可以)。或者他们可以覆盖发送方法(但这不太可能)。所以这是一个部分的解决方案。

因为它不依赖未更改的“onreadystatechange”回调,而是监控“readyState”本身。

我从这里调整了答案:https ://stackoverflow.com/a/7778218/1153227

于 2013-12-21T02:26:12.497 回答
36

试试这个。检测 Ajax 响应,然后我添加了一个条件,使用 XMLHttpRequest 属性 readyState & 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;

修改自: 监控浏览器控制台中的所有 JavaScript 事件

于 2015-02-03T15:55:30.403 回答
21

这可能有点棘手。这个怎么样?

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

我没有测试它,但它看起来或多或少很好。

请注意,如果您使用框架(如 jQuery),它可能不起作用,因为它们可能会onreadystatechange在调用后覆盖send(我认为 jQuery 可以)。或者他们可以覆盖send方法(但这不太可能)。所以这是一个部分的解决方案。

编辑:如今(2018 年初),新的 fetch API变得更加复杂。全局fetch函数也必须以类似的方式被覆盖。

于 2012-05-28T11:06:41.970 回答
4

该问题的现代(截至 2021 年 4 月)答案是使用PerformanceObserver它可以让您同时观察XMLHttpRequest请求和fetch()请求:

<!-- 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>

window.addEventListenr('error', ... )我在我的页面中使用上面的代码片段来记录请求,以便我可以在我的全局回调中将它们报告回母舰。


  • batch.getEntries()函数返回一个 DOM 对象数组PerformanceResourceTiming(因为我们只在监听type: 'resource',否则它将返回一个不同类型对象的数组)。
  • 每个PerformanceResourceTiming对象都有有用的属性,例如:
    • initiatorType属性可以是:
      • 如果请求是由元素引起的,则为 HTML 元素名称(标签名称):
        • 'link'- 请求来自<link>页面中的元素。
        • 'script'- 请求是加载一个<script>.
        • 'img'- 请求是加载一个<img />元素。
        • ETC
      • 'xmlhttprequest'- 请求是由XMLHttpRequest调用引起的。
      • 'fetch'- 请求是由fetch()呼叫引起的。
    • name- 资源/请求的 URI。(如果有重定向,我不确定这是原始请求 URI 还是最终请求 URI)。
    • startTime:注意:这实际上是PerformanceObserver.observe()请求开始时被调用的时间。
    • duration:注意:这实际上是PerformanceObserver.observe()请求完成后被调用的时间:它不仅仅是请求的持续时间。要获得“真实”持续时间,您需要从中startTime减去duration.
    • transferSize:响应中的字节数。
于 2021-04-25T06:47:10.763 回答