JavaScript检测AJAX事件

Cra*_*ent 71 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"
  }
);
Run Code Online (Sandbox Code Playgroud)

使用此代码,无论我在何处/如何调用$ .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();
}
Run Code Online (Sandbox Code Playgroud)

然后,我有一些随机链接一个onclick调用该函数,我的全局AJAX事件侦听器应该能够同时检测到这一请求.好吧,我将该代码添加到我的页面并将其附加到随机链接的onclick(是的,代码本身可行),但上面的jquery"全局事件侦听器"代码未能检测到该调用.

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

那么......这可能吗?有没有办法检测ajax get/post请求,无论是使用通用对象还是从xyz框架完成?或者我只是需要制作重复的代码来处理每个框架,并提前知道正在创建/使用的ajax对象?

编辑:

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

Cra*_*ent 101

好的,这是我到目前为止所提出的:

<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>
Run Code Online (Sandbox Code Playgroud)

方向:

只需将其复制到您的页面上或将其包含在.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它应该适合你.

我已经测试了这个(截至发布日期):当前的Safari,当前的Chrome,当前的FireFox,IE8,IE8(IE7兼容).它目前不适用于IE6,因为IE6使用ActiveX对象,而其他几乎所有其他都使用XMLHttpRequest.

现在我没有任何线索如何,基本上原型/扩展/重载(?)ActiveXObject("Microsoft.XMLHTTP").这就是我目前正在研究的......有人知道吗?

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

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


Séb*_*eur 5

对于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>
Run Code Online (Sandbox Code Playgroud)

  • 是的,那就是我当时所做的事情..但IE6是任何人都不应该支持的东西,特别是因为自2014年4月微软自己停止支持它(通过不支持XP的扩展) (6认同)