有没有办法在使用通用JavaScript(而不是框架)的网页上检测全局AJAX调用(特别是响应)?
我已经在StackOverflow上查看了问题“JavaScript detect an AJAX event”,并尝试将已接受答案的代码修补到我的应用程序中,但它无效。我之前从未对AJAX做过任何事情,我不知道修改它是否有效。
我不需要任何花哨的东西,我只需要检测所有(具体,实际上,但我必须首先检测所有并从那里开始)AJAX响应并将它们修补到IF语句中以供使用。所以,最终,我想要像:
if (ajax.response == "certainResponseType"){
//Code
}
例如,。
更新 我似乎应该澄清一点,我不是在尝试发送请求 - 我正在开发一个内容脚本,我需要能够检测网页的AJAX请求(不是我自己的),所以我可以在检测到响应时执行一个函数。
答案 0 :(得分:31)
以下是一些代码(通过粘贴到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确实)。或者他们可以覆盖send方法(但这不太可能)。 所以这是一个部分解决方案。
因为它不依赖于'onreadystatechange'回调未被更改,而是监视'readyState'本身。
答案 1 :(得分: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年初),the new fetch API变得更加复杂。必须以类似的方式覆盖全局fetch
函数。
答案 2 :(得分:17)
尝试一下。检测Ajax响应,然后使用XMLHttpRequest propoerties 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;
答案 3 :(得分:2)
该问题的现代(截至 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
属性可以是:
'link'
- 请求来自页面中的 <link>
元素。'script'
- 请求加载 <script>
。'img'
- 请求加载一个 <img />
元素。'xmlhttprequest'
- 请求是由 XMLHttpRequest
调用引起的。'fetch'
- 请求是由 fetch()
调用引起的。name
- 资源/请求的 URI。 (如果有重定向,我不确定这是原始请求 URI 还是最终请求 URI)。startTime
:注意:这实际上是自请求开始时调用 PerformanceObserver.observe()
以来的时间。duration
:注意:这实际上是请求完成时调用 PerformanceObserver.observe()
以来的时间:这不仅仅是请求的持续时间 em>。要获得“真实”持续时间,您需要从 startTime
中减去 duration
。transferSize
:响应中的字节数。