简单的jQuery Ajax调用在Internet Explorer中泄漏内存
我创build了一个每秒都可以进行Ajax调用的网页。 在Internet Explorer 7中,它严重泄漏内存(大约15分钟内20 MB)。
程序非常简单。 它只是运行一个使Ajax调用的JavaScript函数。 服务器返回一个空string,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>
如何堵塞这个泄漏? 我有一个真正的应用程序,这样更新一个大桌子,但无人看pipe它会吃掉千兆字节的内存。
编辑 :好的,所以经过一些很好的build议,我修改了代码:
<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是否固有地创build了某种循环引用,如果是的话,我该如何释放它? 顺便说一下,它不会在Firefox中泄漏。
有人build议在另一台虚拟机上运行testing,看看结果是否相同。 我find了一台运行Internet Explorer 8的XP Home的笔记本电脑,而不是设置另一台虚拟机。它显示了同样的问题。
我尝试了一些老版本的jQuery,并得到了更好的结果,但是直到我放弃了jQuery中的Ajax,并且使用了更传统的(和丑陋的)Ajax,问题才完全消失。
这里有一个关于jQuery上的bug的链接 ,以及作为jQuery 1.4.2的一个build议修复的链接:
--- 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; } } };
注 :这是正式固定在jQuery 1.4.4,所以你最好的select是现在就升级。
这个问题似乎是在IE浏览器中使用jQuery 1.4,在较小的程度上,版本是1.2和1.3。
1.4.0,1.4.1和1.4.2都performance出严重的内存泄漏。
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>
这完全摆脱了泄漏。
所以看起来像我必须重复Ajax调用丑陋的旧方式,直到jQuery的人解决这个问题。
我遇到了同样的问题,整个上午都被困住了…直到刚才。 问题是当您设置onreadystatechange
处理程序时创build的循环引用,该IE不够聪明,不能打破。 因此,解决scheme是明确地分解它。 但是,显然你不能从处理程序本身做到这一点(虽然如果你可以的话会很方便)。
神奇的声明:
delete request['onreadystatechange'];
您需要保留为其设置onreadystatechange
的每个XMLHttpRequest
对象的logging。 然后,在readyState
到达4之后的某个时刻,在对象上做你的魔法。 如果您已经在执行重复的AJAX轮询,则检查请求清理的逻辑位置将处于相同的轮询循环中。 我定义了一个简单的RequestTracker
对象来pipe理我的请求。
这对我有效; 我证实它解决了泄漏。 这里有一个特别的链接(我会张贴更多,但StackOverflow不让我):
eval()
将肯定会消耗内存(在将string传递给setTimeout进行评估时会发生eval),请不要在testing中使用它:
setTimeout('testJunk()',1000);
应该:
setTimeout(testJunk, 1000);
另外一个更好的使用总体来说就是setInterval()
对于像你想要的重复操作,试试这个:
setInterval(testJunk, 1000);
你的代码的一个问题是,如果你的ajax请求开始需要一段时间,你将开始用ajax请求来泛滥浏览器和服务器,你应该等到浏览器从服务器返回后再开始下一个。
function testJunk() { $.ajax({ url: 'http://xxxxxxxxxxxxxx/test', // The url returns an empty string dataType: 'html', complete: function(data){ setTimeout(testJunk,1000); } }); } testJunk();
我已经看到了这一点,我不相信这是一个内存泄漏。 只是因为caching,Ajax请求返回没有数据。
添加故意的caching控制,如下所示:
$.ajax({ url: 'http://xxxxxxxxxxxxxx/test', // The url returns an empty string dataType: 'html', cache: false, success: function(data){} }); setTimeout('testJunk()',1000)
这是一些东西在崩溃的东西之一,也就是说,具有caching和XMLHttpRequest和jQuery的具体事情不默认使用cachingclosures。
刚刚遇到这个自己。 我认为最初是和UI库有关,但是在jQuery 1.5交换之后,它就消失了。 对于我正在使用的1.4.2版本。 (1.4.4似乎没有解决这个问题)。
如果您在javascript中使用setinterval并且没有正确清除它,定时器可能会多次启动,导致一堆调用。
尝试类似的东西
var myVar = setInterval(function() { clear() }, 5000); function clear() { clearInterval(myVar); GetData("ServiceLibrary","GetCalls",sdata,Complete); };