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

使用此代码,无论我在哪里/如何调用 \(.post(..),全局事件侦听器都会触发。如果我使用 \).get 或 $.ajax(任何 jquery ajax 方法),它也可以工作,无论我如何/何时调用它(附加为 onclick,在页面加载时,等等)。

但是,我希望能够扩展这个监听器,无论使用什么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();
}

然后我在某个随机链接上对该函数进行了 onclick 调用,我的全局 ajax 事件侦听器 应该能够检测到该请求。好吧,我将该代码添加到我的页面并将其附加到随机链接的 onclick(是的,代码本身有效),但上面的 jquery“全局事件侦听器”代码未能检测到该调用。

我做了更多的挖掘,我知道我基本上可以将对象保存到一个临时对象并用一个“包装器”对象覆盖当前对象,该对象将调用指定的函数然后调用临时函数,但这需要我提前知道创建/使用原始对象的时间。但我不会总是提前知道…

所以……这可能吗?有什么方法可以检测是否发出了 ajax get/post 请求,无论它是使用通用对象还是来自 xyz 框架?或者我是否只需要制作重复的代码来处理每个框架并且提前知道正在创建/使用的 ajax 对象?

编辑:

我忘了提一下,仅仅检测请求的发生是不够的。我还需要捕获请求中发送的数据。下面评论中提供的链接将有助于确定是否发出了“a”请求,但不会发送数据。 ps - 下面链接中提供的答案不是很清楚,至少对我来说是这样。

原文由 CrayonViolent 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 419
2 个回答

好的,这就是我到目前为止的想法:

 <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 的对象。每当发出 AJAX GET 或 POST 请求时,都会调用 s_ajaxListener.callback(),并且可以使用以下属性:

s_ajaxListener.method :使用的 ajax 方法。这应该是 GET 或 POST。注意:该值可能并不总是大写,这取决于特定请求的编码方式。我正在讨论自动将其大写或将其留给 toLowerCase() 以进行不区分大小写的比较是否明智。

s_ajaxListener.url :请求脚本的 url(包括查询字符串,如果有的话)(urlencoded)。我注意到,取决于数据的发送方式和来自哪个浏览器/框架,例如这个值最终可能会成为“”或“+”或“%20”。我正在争论在这里解码它还是留给其他东西的智慧。

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

笔记:

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

我已经在(截至发布日期)进行了测试:Current Safari、Current Chrome、Current FireFox、IE8、IE8(兼容 IE7)。它目前不适用于 IE6,因为 IE6 使用 ActiveX 对象,而几乎所有其他东西都使用 XMLHttpRequest。

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

在我上面测试的每个浏览器下,这都适用于来自通用对象的 AJAX 请求,也适用于来自 jquery 和原型框架的请求。我知道还有其他框架,但 IMO 这两个是主要框架。我可能会 QA MooTools,但除此之外,我可以只测试那些。

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

原文由 CrayonViolent 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

原文由 Sébastien Brodeur 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏