我创建了一个网页,它每秒钟调用一次Ajax。在7中,内存泄漏严重(大约15分钟内20 MB )。
这个程序很简单。它只运行一个进行Ajax调用的JavaScript函数。服务器返回一个空字符串,而JavaScript代码对它没有任何作用。我每秒钟使用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>
如何堵住这个漏洞?我有一个真正的应用程序,它以这种方式更新一个大表,但是如果没有人参与,它将消耗掉千兆字节的内存。
编辑:好的,在提出了一些好的建议之后,我将代码修改为:
<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,而是找到了一台使用8运行XP Home的笔记本电脑,它也出现了同样的问题。
我尝试了一些旧版本的jQuery,并获得了更好的结果,但是直到我放弃了jQuery中的Ajax,使用了更传统(更丑陋)的Ajax,这个问题才完全消失。
发布于 2010-03-12 16:59:32
问题似乎与中的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>
这样就完全消除了泄漏。
因此,在jQuery人员解决这个问题之前,我似乎不得不用丑陋的老方式重复执行Ajax调用。
发布于 2010-04-08 19:11:50
下面是一个链接,用于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;
}
}
};
注意到:这是在jQuery 1.4.4中正式修正的,所以你最好现在就升级。
发布于 2010-04-02 15:59:04
我遇到了同样的问题,整个早上都很困惑.直到几分钟前。问题是在设置onreadystatechange
处理程序时创建的循环引用,IE不够聪明,无法中断。因此,解决办法是显式地打破它。但是,很明显,您不能在处理程序本身中执行此操作(尽管如果可以的话,这样做会很方便)。
神奇的声明:
delete request['onreadystatechange'];
您需要保存设置XMLHttpRequest
的每个onreadystatechange
对象的记录。然后,在readyState
转到4之后的某个时候,对对象执行魔法。如果您已经在执行重复的AJAX轮询,检查需要清理的请求的逻辑位置将位于同一个轮询循环中。我定义了一个简单的RequestTracker
对象来管理我的请求。
这对我有效;我证实它解决了泄漏。这里有一个特别重要的链接(我会发布更多的链接,但StackOverflow不允许我):
https://stackoverflow.com/questions/2429056
复制相似问题