每个ProcessingPayments()都使用了内存增加。 CollectGarbage()没有帮助。使用Drip查看内存使用情况,但不要查看任何DOM泄漏。
我只使用IE8并在旧版本上进行测试。其他不感兴趣的浏览器。
如何在执行此脚本时减少不断增长的内存使用量?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>JS IE XMLHTTP - Memory leaks</title>
</head>
<body onload="ProcessingPayments();locCollectGarbage();">
<script language="JScript">
var toProcessingPayments;
var ProcessingPaymentsPeriod = 1*60*1000;
var SessionCount = 1;
var CollectGarbageCount = 1;
function ProcessPayment(arrParams) {
var e;
var strURL = "http://www.facebook.com/";
var strURLParam = "";
try { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP.6.0"); }
catch (e) { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP"); }
function ProcessPaymentHTTPRequest() {
if (locHTTPRequest.readyState != 4) {
return;
}
if (locHTTPRequest.status != 200) {
document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML
+arrParams.i+" = error code "+locHTTPRequest.status+"<br />";
return false;
}
if (locHTTPRequest.getResponseHeader("Content-Type").indexOf("text/html") < 0) {
document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML
+arrParams.i+" = wrong content type "+locHTTPRequest.getResponseHeader("Content-Type").indexOf("text/html")+"<br />";
return false;
}
try {
document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML
+arrParams.i+" = processed<br />";
return true;
}
catch(e) {
if (locHTTPRequest.responseXML.parseError != 0) {
return false;
}
else {
return false;
}
}
locHTTPRequest.abort();
delete locHTTPRequest["onreadystatechange"];
locHTTPRequest = null;
} // function ProcessPaymentHTTPRequest()
strURLParam = "?"+arrParams.i;
locHTTPRequest.open("get", strURL+strURLParam);
document.getElementById("CurrentSession").innerHTML = document.getElementById("CurrentSession").innerHTML
+arrParams.i+" = request<br />";
locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest;
locHTTPRequest.send(null);
}
function ProcessingPayments(arrPayment) {
var e;
toProcessingPayments = null;
document.getElementById("CurrentSession").innerHTML = "";
for (var i = 0; i < 10; i++) {
ProcessPayment({
i: i
});
}
SessionCount++;
document.getElementById("Session").innerText = SessionCount;
toProcessingPayments = setTimeout(ProcessingPayments, ProcessingPaymentsPeriod);
}
function locCollectGarbage() {
CollectGarbage();
document.getElementById("CollectGarbage").innerText = CollectGarbageCount;
CollectGarbageCount++;
setTimeout(locCollectGarbage, 5*60*1000);
}
</script>
</body>
<p>Sessions: <span id="Session">0</span></p>
<p>CollectGarbage(): <span id="CollectGarbage">0</span></p>
<hr />
<br />
<p>Current session:</p>
<p id="CurrentSession"></p>
</html>
答案 0 :(得分:1)
locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest;
在native-JScript对象(具有范围内的请求对象的ProcessPaymentHTTPRequest
函数)和非JScript对象(XMLHttpRequest
ActiveX对象)之间创建引用循环。正是这种参考循环使IE无法通过GC。
delete locHTTPRequest["onreadystatechange"];
虽然对于本机JavaScript对象来说没问题,但实际上delete
实际上并不能从DOM对象中删除事件处理程序。因此处理程序和引用循环保持不变。通常做的是使用dud值覆盖locHTTPRequest.onreadystatechange
处理程序,例如立即返回的预定义函数,或''
或null
。或者,使用addEventListener
/ attachEvent
及其相应的删除处理程序方法。
CollectGarbage();
那是做什么的?你可以做很多事情来影响JS的GC。
除了:
<script language="JScript">
type="text/javascript"
代替language
。我知道你不关心非IE,但似乎没有任何不兼容和非标准的点。
try { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP.6.0"); }
catch (e) { var locHTTPRequest = new ActiveXObject("MSXML2.XMLHTTP"); }
没有必要这样做。您没有使用较新的MSXML版本的任何功能,因此对于未版本化的XMLHttp
来说非常丰富。另外,首先选择native-JS XMLHttpRequest
。不仅因为它存在于其他浏览器上,而且因为它更高效,并且作为原生JS,不会导致内存泄漏。
最佳:为IE6添加后备:
if (!window.XMLHttpRequest && 'ActiveXObject' in window) {
window.XMLHttpRequest= function() {
return new ActiveXObject('MSXML2.XMLHttp');
}
}
然后在任何地方使用标准new XMLHttpRequest()
。
locHTTPRequest.send(null);
即使对于IE,这也是非标准的。如果您不想发送任何内容,请省略data参数,而不是提供null
。