代码之家  ›  专栏  ›  技术社区  ›  CrayonViolent

javascript检测到Ajax事件

  •  69
  • CrayonViolent  · 技术社区  · 14 年前

    好的,所以基本上我想在一个页面上有一些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”请求,但不能发送数据。P.S.-下面的链接中提供的答案不是很清楚,至少对我来说是这样。

    2 回复  |  直到 6 年前
        1
  •  101
  •   CrayonViolent    10 年前

    好吧,这就是我到目前为止想出来的:

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

    方向:

    只需将它c/p到您的页面上,或者将它包含在.js文件中或其他任何文件中。这将创建一个名为s_Ajaxlistener的对象。每当发出Ajax GET或POST请求时,都会调用s撘ajaxlistener.callback(),并提供以下属性:

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

    s砗ajaxlistener.url :请求的脚本的URL(包括查询字符串,如果有)(urlencoded)。我注意到,这取决于数据是如何发送的,以及从哪个浏览器/框架发送的,例如,该值最终可能是“”或“+”或“%20”。我正在讨论在这里解码它或把它留给其他东西的智慧。

    S?ajaxlistener.数据 :发送的数据(如果有),例如:foo=bar&a=b(与.url相同的“issue”,其为url编码)

    笔记:

    事实上, 这与IE6不兼容 . 这个解决方案对我来说还不够好,因为我希望它与IE6兼容。但由于很多人不关心IE6,我决定将我的解决方案发布到当前状态,因为如果你不关心IE6,它应该对你有用。

    我已经测试过这个了 (截至发布日期):当前Safari、当前Chrome、当前Firefox、IE8、IE8(兼容IE7)。它目前不能与IE6一起工作,因为IE6使用ActiveX对象,而实际上其他所有对象都使用XMLHttpRequest。

    现在我不知道怎么做,基本上是原型/扩展/过载(?)ActiveXObject(“microsoft.xmlhttp”)。这是我目前正在研究的…有人马上知道吗?

    在我上面测试的每一个浏览器中,这都可以处理来自通用对象以及来自jquery和原型框架的Ajax请求。我知道还有其他的框架,但在我看来,这两个是主要的框架。我可能会对moootools进行质量保证,但除此之外,我可以只测试这些工具。

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

        2
  •  5
  •   Sébastien Brodeur    10 年前

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