JavaScript 检测 AJAX 事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3596583/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JavaScript detect an AJAX event
提问by Crayon Violent
Okay so basically I want to have a bit of javascript on a page that somehow attaches some kind of global event listener that can detect and do something if an ajax request is made (without directly calling it from the call), regardless of how the ajax call is made.
好的,所以基本上我想在页面上有一些 javascript,它以某种方式附加某种全局事件侦听器,如果发出 ajax 请求,则可以检测并执行某些操作(不直接从调用中调用它),无论 ajax 是如何调用的进行了呼叫。
I figured out how to do this with jquery - if the ajax request is being done byjquery. Here is an example code for this:
我想出了如何用 jquery 做到这一点 - 如果 ajax 请求是由jquery完成的。这是一个示例代码:
$.post(
// requested script
'someScript.php',
// data to send
{
'foo' : 'bar',
'a' : 'b'
},
// receive response
function(response){
// do something
}
); // .post
// global event listener
$(document).ajaxSend(
function(event,request,settings){
alert(settings.url); // output: "someScript.php"
alert(settings.data); // output: "foo=bar&a=b"
}
);
With this code, regardless of where/how I call $.post(..), the global event listener will trigger. It also works if I use $.get or $.ajax (any jquery ajax methods), regardless of how/when I call it (attached as an onclick, on page load, whatever).
使用此代码,无论我在何处/如何调用 $.post(..),全局事件侦听器都会触发。如果我使用 $.get 或 $.ajax(任何 jquery ajax 方法),它也可以工作,无论我如何/何时调用它(附加为 onclick、页面加载等)。
However, I want to be able to extend this listener to trigger regardless of what js framework is used, or even if no framework is used. So for instance if I were to alsohave on a page the following code (generic ajax code from w3schools):
但是,无论使用什么 js 框架,或者即使没有使用框架,我都希望能够扩展此侦听器以触发。例如,如果我在页面上也有以下代码(来自 w3schools 的通用 ajax 代码):
function loadXMLDoc()
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","test.txt",true);
xmlhttp.send();
}
And then I have on some random link an onclick call to that function, my global ajax event listener should be able to alsodetect this request. Well I added that code to my page and attached it to a random link's onclick (yes, the code itself works), but the jquery "global event listener" code above failed to detect that call.
然后,我有一些随机链接到该函数一个onclick调用,我的全局AJAX事件侦听器应该能够同时检测到这一请求。好吧,我将该代码添加到我的页面并将其附加到随机链接的 onclick(是的,代码本身有效),但上面的 jquery“全局事件侦听器”代码未能检测到该调用。
I did some more digging and I know I can basically save the object to a temp object and overwrite the current object with a "wrapper" object that will call a specified function and then call the temp function, but this requires me to know ahead of time the original object being created/used. But I won't always know that ahead of time...
我做了更多的挖掘,我知道我基本上可以将对象保存到临时对象并用“包装器”对象覆盖当前对象,该对象将调用指定的函数然后调用临时函数,但这需要我提前知道创建/使用原始对象的时间。但我不会总是提前知道...
So...is this possible? Is there some way to detect an ajax get/post request was made, regardless of whether it was done with a generic object or from xyz framework? Or am I just going to have to make duplicate code to handle each framework and also know ahead of time the ajax object(s) being created/used?
所以……这可能吗?是否有某种方法可以检测到 ajax get/post 请求是否已发出,无论它是使用通用对象还是来自 xyz 框架完成的?或者我是否只需要制作重复的代码来处理每个框架,并提前知道正在创建/使用的 ajax 对象?
edit:
编辑:
I forgot to mention that it is not enough to detect that a request occurred. I also need to capture the data being sent in the request. The link provided in the comments below will help figure out if "a" request was made, but not get the data sent. p.s. - the answer provided in the link below is not very clear, at least to me anyways.
我忘了说,仅仅检测请求发生是不够的。我还需要捕获请求中发送的数据。下面评论中提供的链接将有助于确定是否发出了“a”请求,但不会发送数据。ps - 下面链接中提供的答案不是很清楚,至少对我来说是这样。
回答by Crayon Violent
Okay this is what I have come up with so far:
好的,这是我到目前为止想出的:
<script type='text/javascript'>
var s_ajaxListener = new Object();
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
// this.method :the ajax method used
// this.url :the url of the requested script (including query string, if any) (urlencoded)
// this.data :the data sent, if any ex: foo=bar&a=b (urlencoded)
}
XMLHttpRequest.prototype.open = function(a,b) {
if (!a) var a='';
if (!b) var b='';
s_ajaxListener.tempOpen.apply(this, arguments);
s_ajaxListener.method = a;
s_ajaxListener.url = b;
if (a.toLowerCase() == 'get') {
s_ajaxListener.data = b.split('?');
s_ajaxListener.data = s_ajaxListener.data[1];
}
}
XMLHttpRequest.prototype.send = function(a,b) {
if (!a) var a='';
if (!b) var b='';
s_ajaxListener.tempSend.apply(this, arguments);
if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
s_ajaxListener.callback();
}
</script>
DIRECTIONS:
方向:
Just c/p this onto your page or include it in a .js file or whatever. This will create an object called s_ajaxListener. Whenever an AJAX GET or POST request is made, s_ajaxListener.callback() is called, and the following properties are available:
只需将其 c/p 到您的页面上或将其包含在 .js 文件或其他文件中。这将创建一个名为 s_ajaxListener 的对象。每当发出 AJAX GET 或 POST 请求时,都会调用 s_ajaxListener.callback(),并且以下属性可用:
s_ajaxListener.method: The ajax method used. This should be either GET or POST. NOTE: the value may not always be uppercase, it depends on how the specific request was coded. I'm debating the wisdom of automatically upper-casing it or leaving it to something else to toLowerCase() for a case-insensitive comparison.
s_ajaxListener.method:使用的 ajax 方法。这应该是 GET 或 POST。注意:该值可能并不总是大写,这取决于特定请求的编码方式。我正在讨论自动将其大写或将其留给 toLowerCase() 以进行不区分大小写比较的智慧。
s_ajaxListener.url: The url of the requested script (including query string, if any) (urlencoded). I have noticed, depending on how the data is sent and from which browser/framework, for example this value could end up being as " " or "+" or "%20". I am debating the wisdom of decoding it here or leave it to something else.
s_ajaxListener.url:请求脚本的 url(包括查询字符串,如果有)(urlencoded)。我注意到,根据数据的发送方式以及来自哪个浏览器/框架,例如,此值可能最终为“”或“+”或“%20”。我正在辩论在这里解码它的智慧还是将其留给其他东西。
s_ajaxListener.data: the data sent, if any ex: foo=bar&a=b (same 'issue' as .url with it being url-encoded)
s_ajaxListener.data:发送的数据,如果有的话,例如:foo=bar&a=b(与 .url 相同的“问题”,它是 url 编码的)
NOTES:
笔记:
As it stands, this is not IE6 compatible. this solution is not quite good enough for me, as I want it to be IE6 compatible. But since a lot of other people don't care about IE6, I decided to post my solution in its current state, as it should work for you if you don't care about IE6.
就目前而言,这与 IE6 不兼容。这个解决方案对我来说还不够好,因为我希望它与 IE6 兼容。但是由于很多其他人不关心 IE6,我决定以当前状态发布我的解决方案,因为如果您不关心 IE6,它应该对您有用。
I have tested this in(as of this posted date): Current Safari, Current Chrome, Current FireFox, IE8, IE8 (IE7 Compatible). It doesn't currently work with IE6 because IE6 uses an ActiveX object, while virtually everything else uses XMLHttpRequest.
我已经在(截至本发布日期)进行了测试:Current Safari, Current Chrome, Current FireFox, IE8, IE8 (IE7 Compatible)。它目前不适用于 IE6,因为 IE6 使用 ActiveX 对象,而实际上其他所有内容都使用 XMLHttpRequest。
Right now I don't have any clue how to, well basically prototype/extend/overload (?) ActiveXObject("Microsoft.XMLHTTP"). This is what I am currently researching...does anybody know offhand?
现在我没有任何线索,基本上是原型/扩展/重载(?)ActiveXObject(“Microsoft.XMLHTTP”)。这就是我目前正在研究的……有人知道吗?
Under each of the browsers I tested above, this works with AJAX requests from a generic object, and also from the jquery and prototype frameworks. I know there are other frameworks out there, but IMO these 2 are the major ones. I might possibly QA MooTools, but other than that, I'm fine with only testing those.
在我上面测试的每个浏览器下,这适用于来自通用对象以及来自 jquery 和原型框架的 AJAX 请求。我知道还有其他框架,但 IMO 这两个是主要的。我可能会 QA MooTools,但除此之外,我只测试那些就可以了。
If Anybody wants to contribute by testing and posting results about other browsers and/or frameworks, it would be appreciated :)
如果有人想通过测试和发布有关其他浏览器和/或框架的结果做出贡献,我们将不胜感激:)
回答by Sébastien Brodeur
For IE 6 compatibility, how about :
对于 IE 6 兼容性,如何:
<script type='text/javascript'>
var s_ajaxListener = new Object();
// Added for IE support
if (typeof XMLHttpRequest === "undefined") {
XMLHttpRequest = function () {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
catch (e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch (e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); }
catch (e) {}
throw new Error("This browser does not support XMLHttpRequest.");
};
}
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;
s_ajaxListener.callback = function () {
// this.method :the ajax method used
// this.url :the url of the requested script (including query string, if any) (urlencoded)
// this.data :the data sent, if any ex: foo=bar&a=b (urlencoded)
}
XMLHttpRequest.prototype.open = function(a,b) {
if (!a) var a='';
if (!b) var b='';
s_ajaxListener.tempOpen.apply(this, arguments);
s_ajaxListener.method = a;
s_ajaxListener.url = b;
if (a.toLowerCase() == 'get') {
s_ajaxListener.data = b.split('?');
s_ajaxListener.data = s_ajaxListener.data[1];
}
}
XMLHttpRequest.prototype.send = function(a,b) {
if (!a) var a='';
if (!b) var b='';
s_ajaxListener.tempSend.apply(this, arguments);
if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
s_ajaxListener.callback();
}
</script>

