JavaScript 检测 AJAX 事件

好的,基本上我想在一个页面上有一个 javascript,它以某种方式附加了某种全局事件监听器,它可以检测和执行 Ajax 请求(不直接从调用中调用它) ,而不管 Ajax 调用是如何进行的。

我弄明白了如何用 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"
}
);

使用这段代码,不管我在何处/如何调用 $。邮寄(。.)全局事件侦听器将触发。如果我使用 $,它也可以工作。得到或 $。Ajax (任何 jquery ajax 方法) ,不管我如何/何时调用它(作为 onclick 附加,在页面加载时,等等)。

但是,我希望能够扩展这个侦听器来触发,而不管使用的是什么 js 框架,或者即使没有使用任何框架。例如,如果我在 还有页面上有以下代码(来自 w3school 的通用 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();
}

然后我有一些随机链接一个 onclick 调用该函数,我的全局 ajax 事件侦听器应该能够检测到这个请求。我将这段代码添加到我的页面,并将其附加到一个随机链接的 onclick (是的,代码本身是可以工作的) ,但是上面的 jquery“ global event listen”代码未能检测到这个调用。

我做了一些深入的研究,我知道我基本上可以把对象保存到一个临时对象,然后用一个“包装器”对象覆盖当前对象,这个对象将调用一个指定的函数,然后调用临时函数,但是这需要我提前知道原始对象被创建/使用。但我不会总是提前知道。

那么... 这可能吗?是否有某种方法来检测 Ajax get/post 请求是否已经发出,而不管它是使用通用对象还是从 xyz 框架发出的?或者我只需要重复编写代码来处理每个框架,并提前知道正在创建/使用的 ajax 对象?

编辑:

我忘了提到,仅仅检测到发生了请求是不够的。我还需要捕获在请求中发送的数据。下面的评论中提供的链接将帮助确定是否发出了“ a”请求,但是没有发送数据。附注-以下连结所提供的答案并不十分清楚,至少对我来说是这样。

77243 次浏览

好了,这就是我目前想到的:

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

导演:

只需将此文件传送到您的页面或将其包含在。Js 文件什么的。这将创建一个名为 s _ ajaxListener 的对象。每当发出 AJAXGET 或 POST 请求时,s _ ajaxListener。调用 callback () ,并且可以使用以下属性:

S _ ajaxListener.方法 : 使用 ajax 方法。这应该是 GET 或 POST。注意: 该值不一定总是大写,它取决于特定请求的编码方式。我正在讨论是否应该自动加大它的大小写,或者将它留给 toLowerCase ()进行不区分大小写的比较。

S _ ajaxListener.Url : 请求脚本的 url (包括查询字符串,如果有的话)(urlencode)。我注意到,这取决于数据是如何发送的,以及从哪个浏览器/框架发送的,例如,这个值最终可能是“”或“ +”或“% 20”。我在讨论是在这里破译还是交给别人。

S _ ajaxListener. data : 发送的数据(如果有的话) : foo = bar & a = b (与. url 相同的“问题”,它是 url 编码的)

备注:

就目前而言,这与 IE6不兼容。这个解决方案对我来说还不够好,因为我希望它与 IE6兼容。但是因为很多其他人不关心 IE6,我决定把我的解决方案发布到它的当前状态,因为如果你不关心 IE6,它应该对你有用。

我已经在 (截至发布日期)中测试过了: Current Safari,Current Chrome,Current FireFox,IE8,IE8(IE7 Compatible)。它目前不能用于 IE6,因为 IE6使用 ActiveX 对象,而实际上其他所有对象都使用 XMLHttpRequest。

现在我还不知道怎么做,基本上就是原型/扩展/超载(?)ActiveXObject (“ Microsoft.XMLHTTP”)。这就是我目前正在研究的... 有人知道吗?

在我上面测试的每个浏览器中,这都可以处理来自通用对象的 AJAX 请求,也可以处理来自 jquery 和原型框架的 AJAX 请求。我知道还有其他的框架,但是我认为这两个是主要的框架。我可能会使用 QA MooTools,但除此之外,我只测试这些工具就可以了。

如果有人想通过测试和发布其他浏览器和/或框架的结果来做出贡献,我们将不胜感激:)

对于 IE6的兼容性,如下:

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

由于需要通过其他脚本(XHR 和/或提取)来监听 AJAX 事件,并受到这篇 SO 文章的启发,我在 GitHub 上创建了一个非常通用的 AjaxListener.js小工具(注意: IE < 7不支持)。

基本用法:

function mylistener(req, res)
{
// API is either 'xhr' or 'fetch'
console.log('REQUEST', 'API', req.getAPI(), 'Method', req.getMethod(), 'URL', req.getURL(), 'Headers', req.getHeaders(), 'Body', req.getBody());
console.log('RESPONSE', 'API', res.getAPI(), 'Status', res.getStatus(), 'URL', res.getURL(), 'Headers', res.getHeaders(), 'Body', res.getBody());
}


AjaxListener.install().onRequest(mylistener);


//AjaxListener.onRequest(mylistener, false); // unlisten


//AjaxListener.uninstall(); // uninstall

希望有用。