如何在使用定期AJAX / XMLHttpRequest调用时修复浏览器的内存增长?

时间:2012-10-01 12:50:01

标签: ajax memory-leaks xmlhttprequest refresh intervals

我花了整个周末在我用Dojo编写的Web应用程序中详细说明内存增长问题。

Web应用程序将“永远运行”,因此无法重新启动浏览器。

应用程序定期更新服务器(无跨域)的动态数据;每5秒钟,进行一次AJAX调用以将新数据检索为JSON。

通过让应用程序运行几个小时,我发现浏览器的内存不断增长(最新的Chrome和Firefox,无论是最新的Windows还是Mac OS X)。

起初,我认为Dojo导致了这种行为。事实上,通过使用XMLHttpRequest对象切换到本机实现,我可以大大减少内存增长,但它仍然存在。随着每个AJAX请求,内存增长一点点(大约4-8KB)。

我已经尝试过:

我有......

  • ...尝试使用其他框架,如jQuery,YUI等。 - 没有效果
  • ...切换到使用原生`XMLHttpRequest`对象 - 帮助很多,但不完全
  • ...在检索到的数据之后停用DOM操作 - 无效
  • ...通过设置为“null”重置`xhr`并在每次迭代后删除它 - 无效
  • ...在每次迭代后将onreadystatechange处理程序重置为null或空方法 - 无效
  • ...重用了`xhr`对象和`onreadystatechange`处理程序,因为它始终是相同的 - 没有效果

因此,即使我没有做任何事情(如下面第一个StackOverflow链接中所述)和加载的数据,内存使用量也会增加:

我已经读过的内容:

我的测试HTML代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Native XHR Async</title>
</head>
<body>
<script>

var update = document.createElement("div");
document.body.appendChild(update);

var timeout = null;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = onReadyState;

function loadData()
{
    xhr.open("GET","memory-leak.json?" + new Date().getTime());
    xhr.send(null);
}

function onReadyState()
{
   if (this.readyState === 4)
   {
       if( this.status === 200 )
       {
           update.innerHTML = "";
           update.innerHTML = this.responseText;
       }

       if( timeout !== null )
       {
           clearTimeout(timeout);
           delete timeout;
       }

       timeout = setTimeout(loadData, 1000);
   }       
}

loadData();

</script>

</body>
</html>

我的测试JSON(在同一目录中):

{
    "errorstatus":"Okay",
    "B0":{"P":"0 Watt"},
    "E0":{"P":"28 Watt"},
    "Z0":{"P":"28 Watt"},
    "S0":{"P":"0 Watt","SOC":"74%"},
    "Z1":{"P":"0 Watt"},
    "R0":0,
    "R1":0,
    "R2":0,
    "date":"29.09.2012 09:23:19",
    "Version":"Sep 28 2012-15.22"
}

我对此问题没有任何解释,所以非常感谢任何帮助。如果您需要任何进一步的信息,请不要犹豫,问我。

1 个答案:

答案 0 :(得分:2)

XmlHttpRequest将缓存每个响应,这就是您附加日期以使URL唯一的原因。

缓存正常写入磁盘,但也会保存在XmlHttpRequest中,只要它存在就会发出请求。

您应该为每个请求使用一个实例并将其销毁,或者确保通过编译指示和xhr设置禁用缓存。