我创建了一个网页,每秒进行一次Ajax调用。在Internet Explorer 7中,它严重泄漏内存(大约15分钟内20 MB)。
该程序非常简单。它只是运行一个进行Ajax调用的JavaScript函数。服务器返回一个空字符串,而JavaScript代码则不执行任何操作。我setTimeout过去每秒钟运行一次该函数,并且我正在使用Drip来观看该事件。
setTimeout
来源如下:
<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>
如何堵塞这种泄漏?我有一个真正的应用程序,它会以这种方式更新大表,但是如果不加注意,它将占用数GB的内存。
编辑 :好的,所以在提出一些好的建议之后,我将代码修改为:
<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>
不过,这似乎没有什么区别。我没有对DOM做任何事情,如果我注释掉Ajax调用,则内存泄漏将停止。因此,看起来泄漏完全在Ajax调用中。jQuery Ajax是否会固有地创建某种循环引用?如果是,我如何释放它?顺便说一下,它不会在Firefox中泄漏。
有人建议在另一台VM上运行测试,然后查看结果是否相同。我没有设置另一台VM,而是发现了一台运行带有Internet Explorer 8的XP Home的笔记本电脑。它出现了同样的问题。
我尝试了一些旧版本的jQuery并获得了更好的结果,但是直到我放弃jQuery中的Ajax并使用了更传统(更丑陋)的Ajax时,问题才完全消失。
问题似乎出在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分钟后大约100 KB)。
我还尝试了一种以更传统的方式调用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>
这完全消除了泄漏。
因此,看来我必须重复我的Ajax调用丑陋的旧方法,直到jQuery专家们解决了这个问题。