2010-09-04 117 views
0

每个ProcessingPayments()使用的内存增加。 CollectGarbage()没有帮助。使用滴水查看内存使用情况,但不要查看任何DOM泄漏。IE JS内存泄漏,而XMLHTTP请求

我只使用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

您是否需要支持IE 6?如果没有,为什么不使用本地'XMLHttpRequest'而不是使用ActiveX对象?也许这解决了你的问题。 – 2010-09-04 17:00:59

+0

2Mercel Korpel:我无法尝试使用XMLHttpRequest,因为我收到一条错误消息“访问被拒绝”(跨域请求,因为这个HTML基于本地计算机和URL位于facebook)。 所有设置,以防止这个错误,但内置XMLHttpRequest不起作用。 – plr 2010-09-04 19:45:45

回答

1
locHTTPRequest.onreadystatechange = ProcessPaymentHTTPRequest; 

创建本机的JScript对象(ProcessPaymentHTTPRequest函数,它有请求对象的范围)和非JScript的对象(XMLHttpRequest ActiveX对象)之间的参考循环。正是这种参考回路导致IE无法通过GC。

delete locHTTPRequest["onreadystatechange"]; 

虽然这将是一个本地JavaScript对象确定,在现实中delete不实际工作,从一个DOM对象中删除的事件处理程序。所以处理程序和参考循环保持不变。相反,通常会使用Dud值(例如立即返回的预定义函数)或''null覆盖locHTTPRequest.onreadystatechange处理程序。或者,使用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。另外,首先去原生-JS XMLHttpRequest。不仅仅是因为它存在于其他浏览器上,而且因为它更高效,而且是原生JS,不会导致内存泄漏。

最佳:添加备用的IE6:

if (!window.XMLHttpRequest && 'ActiveXObject' in window) { 
    window.XMLHttpRequest= function() { 
     return new ActiveXObject('MSXML2.XMLHttp'); 
    } 
} 

,然后用标准的new XMLHttpRequest()无处不在。

locHTTPRequest.send(null); 

即使对于IE,这也是非标准的。如果您不想发送任何内容,请省略数据参数,而不是提供null

+0

我不能尝试使用原生XMLHttpRequest,因为我收到一条错误消息“访问被拒绝”(跨域请求,因为这个HTML基于本地计算机和URL位于facebook)。所有防止此错误的设置都是通过ActiveXH对象和XMLHttp跨域进行的,但内置XMLHttpRequest不起作用。 – plr 2010-09-04 19:55:55

+0

我改变代码与您的建议: 1.更改删除locHTTPRequest [“onreadystatechange”]; to locHTTPRequest.onreadystatechange = null; 2.禁用CollectGarbage(); 3.