JavaScript:检测 AJAX 请求

Posted

技术标签:

【中文标题】JavaScript:检测 AJAX 请求【英文标题】:JavaScript: Detect AJAX requests 【发布时间】:2012-06-02 18:01:09 【问题描述】:

有没有什么方法可以使用通用 javascript(不使用框架)检测网页上的全局 AJAX 调用(尤其是响应)?

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

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

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

,例如。

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

【问题讨论】:

在我最终来到这里之前,我总是广泛地用谷歌搜索这些东西。我什至在发布之前检查了 *** 本身。 关于您的更新我认为这在浏览器扩展之外是不可能的。 你不认为浏览器扩展不可能吗?我不明白为什么不,请注意。它只运行标准的 JavaScript。 如果我没听错的话:我想说的是,我认为只有可以在浏览器扩展中实现。 那么应该没有问题,因为内容脚本是浏览器扩展的一部分。 (对不起,我上次评论的混乱性质。我编辑了它,忘了删除第一个“不”) 【参考方案1】:

这里有一些代码(通过粘贴到 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://***.com/a/7778218/1153227

【讨论】:

这种情况下有没有办法查出发送的URL?【参考方案2】:

试试这个。检测 Ajax 响应,然后我添加了一个条件,使用 XMLHttpRequest 属性 readyState 和状态来运行函数,如果响应状态 = 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;

修改自: Monitor all JavaScript events in the browser console

【讨论】:

这对我有用。对***的请求进行了测试,它可靠地检测到了完整的状态。然而,从怪异接受的答案中截取的片段对我不起作用。 这正是我需要的!【参考方案3】:

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

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),它可能不起作用,因为它们可能会在调用 send 后覆盖 onreadystatechange(我认为 jQuery 可以)。或者他们可以覆盖send 方法(但这不太可能)。所以这是部分解决方案。

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

【讨论】:

@BenHooper 因为它目前不执行任何操作 - 您需要在 onreadystatechange 处理程序中添加您自己的代码。它对我有用(刚刚测试过)。你在使用框架吗? 对不起,我应该提到我用简单的alert("AJAX"); 替换了评论。还是一无所获。另外,我现在已经用更多信息更新了我的问题。 @BenHooper 有三种可能性:(1)框架覆盖 XMLHttpRequest 对象(如果是这样,那么我担心你无能为力:(除非你覆盖框架:]), (2) AJAX 请求没有结束,(3) 您正在尝试跨域 AJAX(但随后您会在控制台中看到错误)。尝试将 alert 放在 if 之外,看看会发生什么(顺便说一句:我的代码中有一个错字:最后一行有三倍p)。 (1) 我没有积极使用框架(事实上,我正在积极尝试不这样做),但 Chrome 的框架可能会干扰。 (2) 网站的内容已经加载,所以应该已经结束。 (3) 是的,我注意到并改变了它。我现在就试试你的建议。 :) 嗯.. 仍然没有做任何事情。 :|【参考方案4】:

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

Detect fetch API request on web page in JavaScript Detect ajax requests from raw html
<!-- 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>

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


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

【讨论】:

以上是关于JavaScript:检测 AJAX 请求的主要内容,如果未能解决你的问题,请参考以下文章

检测由AJAX请求调用的Iframe的滚动事件

ajax请求, 前后端, JavaScript与java代码示例

AJAX

使用 JavaScript 检测 HTTPS [重复]

当用户完成输入而不是按键时运行javascript函数?

原生javascript发送ajax请求及服务端处理