简单的jQuery Ajax调用在Internet Explorer中泄漏内存

Tho*_*ane 40 ajax jquery memory-leaks

我创建了一个每秒进行一次Ajax调用的网页.在Internet Explorer 7中,它严重泄漏内存(大约15分钟内20 MB).

该计划非常简单.它只运行一个JavaScript函数来进行Ajax调用.服务器返回一个空字符串,JavaScript代码不对其执行任何操作.我用它setTimeout来每秒运行一次这个功能,而我正在使用Drip来观察这个东西.

这是来源:

<html>
  <head>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load('jquery', '1.4.2');
      google.load('jqueryui', '1.7.2');
    </script>
    <script type="text/javascript">
      setTimeout('testJunk()',1000);
      function testJunk() {
        $.ajax({ url: 'http://xxxxxxxxxxxxxx/test', // The url returns an empty string
                 dataType: 'html',
                 success: function(data){}
               });
        setTimeout('testJunk()',1000)
      }
    </script>
  </head>
  <body>
    Why is memory usage going up?
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

怎么堵这个漏洞?我有一个真正的应用程序,以这种方式更新一个大表,但无人看管它将消耗千兆字节的内存.

编辑:好的,所以经过一些好的建议后,我将代码修改为:

<html>
  <head>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load('jquery', '1.4.2');
      google.load('jqueryui', '1.7.2');
    </script>
    <script type="text/javascript">
      setTimeout(testJunk,1000);
      function testJunk() {
        $.ajax({ url: 'http://xxxxxxxxxxxxxx/test', // The url returns an empty string
                 dataType: 'html',
                 success: function(data){setTimeout(testJunk,1000)}
               });
      }
    </script>
  </head>
  <body>
    Why is memory usage going up?
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

但它似乎没有任何区别.我没有对DOM做任何事情,如果我注释掉Ajax调用,内存泄漏就会停止.所以看起来泄漏完全在Ajax调用中.jQuery Ajax本身是否会创建某种循环引用,如果是这样,我该如何释放它?顺便说一句,它不会在Firefox中泄漏.

有人建议在另一个VM中运行测试,看看结果是否相同.我找到了一台运行带有Internet Explorer 8的XP Home的笔记本电脑,而不是设置另一台虚拟机.它出现了同样的问题.

我尝试了一些旧版本的jQuery并获得了更好的结果,但问题并没有完全消失,直到我放弃了jQuery中的Ajax并使用更传统(和丑陋)的Ajax.

Ryl*_*ley 19

这是jQuery上的bug 的链接,以及作为jQuery 1.4.2的建议修复:

--- jquery-1.4.2.js     2010-04-08 12:10:20.000000000 -0700
+++ jquery-1.4.2.js.fixed       2010-04-08 12:10:38.000000000 -0700
@@ -5219,7 +5219,7 @@

                            // Stop memory leaks
                            if ( s.async ) {
-                                       xhr = null;
+                                       xhr.onreadystatechange = null; xhr.abort = null; xhr = null;
                            }
                    }
            };
Run Code Online (Sandbox Code Playgroud)

注意:这是在jQuery 1.4.4中正式修复的,所以最好的办法是立即升级.


Tho*_*ane 8

问题似乎在于Internet Explorer中的jQuery 1.4,以及版本1.2和1.3的较小程度.

1.4.0,1.4.1和1.4.2都表现出严重的内存泄漏.

1.2.3,1.2.6,1.3.0,1.3.1和1.3.2都表现出小得多的泄漏(10分钟后约100KB).

我还尝试了一个以更传统的方式调用Ajax的程序版本:

<html>
  <head>
    <script language="javascript" type="text/javascript">
      function getHTTPObject() {
        var xmlhttp;
        /*@cc_on
        @if (@_jscript_version >= 5)
          try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
          } catch (e) {
            try {
              xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
              xmlhttp = false;
            }
          }
        @else
        xmlhttp = false;
        @end @*/
        if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
          try {
            xmlhttp = new XMLHttpRequest();
            if (xmlhttp.overrideMimeType) {
              xmlhttp.overrideMimeType("text/xml"); 
            }
          } catch (e) {
            xmlhttp = false;
          }
        }
        return xmlhttp;
      }
      var ajaxObject = getHTTPObject();
      setTimeout(testJunk,1000);
      function testJunk() {
        ajaxObject.open('POST', 'http://XXXXXXXXXXXXXXX/delme2', true);
        ajaxObject.onreadystatechange = handleAjaxResponse;
        ajaxObject.send(null);
      }
      function handleAjaxResponse() {
        if (ajaxObject.readyState==4) {
          setTimeout(testJunk,1000);
        }
      }
    </script>
  </head>
  <body>
    <div id="test">Why is memory usage going up?</div>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

这完全摆脱了泄漏.

因此看起来我必须以丑陋的旧方式重复Ajax调用,直到jQuery人员解决这个问题.


Haw*_*Bin 7

我遇到了同样的问题,整个上午都被困住了......直到不久前.问题是在设置onreadystatechange处理程序时创建的循环引用,即IE不够智能,无法中断.因此,解决方案是明确地打破它.但是,显然你不能在处理程序本身内做到这一点(尽管你可以这样做会很方便!).

神奇的声明:

delete request['onreadystatechange'];
Run Code Online (Sandbox Code Playgroud)

您需要记录XMLHttpRequest您设置的每个对象onreadystatechange.然后,在readyState转到4 之后的某个时刻,在对象上做你的魔法.如果您已经在执行重复的AJAX轮询,则检查清理请求的逻辑位置将在同一个轮询循环中.我定义了一个简单的RequestTracker对象来管理我的请求.

这对我有用; 我证实它解决了泄漏问题.这是一个特别引导方式的链接(我会发布更多,但StackOverflow不让我):


Nic*_*ver 5

eval() 肯定会吃掉内存(当传递字符串到setTimeout进行评估时会发生eval),不要在测试中使用它:

setTimeout('testJunk()',1000);
Run Code Online (Sandbox Code Playgroud)

应该:

setTimeout(testJunk, 1000);
Run Code Online (Sandbox Code Playgroud)

另外一个更好的用途是setInterval()对你想要的重复操作,试试这个:

setInterval(testJunk, 1000);
Run Code Online (Sandbox Code Playgroud)