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

Posted

技术标签:

【中文标题】使用定期 AJAX/XMLHttpRequest 调用时如何修复浏览器的内存增长?【英文标题】:How to fix browser's memory growth when using periodic AJAX/XMLHttpRequest calls? 【发布时间】:2012-09-22 07:44:45 【问题描述】:

我花了整个周末来详细说明我用 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` 处理程序,因为它们始终相同 - 无效

因此,即使我对加载的数据什么都不做(如下面的第一个 *** 链接中所述),内存使用量也会增加:

我已经阅读的内容:

Memory Leak with an XMLHttpRequest and setInterval Automatic web-page refresh memory leak using XMLHttpRequest Memory-leak at a wrapped XMLHttpRequest function http://forum.jquery.com/topic/memory-leaks-with-ajax-calls 还有更多...

我的测试 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"

我对这个问题没有任何解释,因此非常感谢任何帮助。如果您需要有关此的任何进一步信息,请随时问我。

【问题讨论】:

打开的时间越长,页面使用的内存越多,这似乎很正常。您应该担心的是当页面关闭时浏览器是否无法取回内存。 感谢您的回复!当浏览器选项卡关闭并再次重新打开时,问题就消失了。但正如我所说,这不是一个选项,因为应用程序应该永久运行 - 此外,页面刷新也不会清空内存......我真的不明白为什么浏览器不摆脱这些旧的 ajax请求,即使我尝试“准备”它们进行垃圾收集? 您最终找到满意的解决方案了吗?面临完全相同的问题。 我在 Safari (Mac) 上也遇到了同样的问题。我们的显示也永远运行,我使用 XMLHttpRequest 定期与 node.js 服务器通信。如果您确实找到了解决方案,请告诉我们:-) 不幸的是,在我们的案例中,唯一的解决方案是在给定时间后重新加载页面。所以我们将时间间隔设置为每天刷新一次页面。 【参考方案1】:

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

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

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

【讨论】:

您好 Rob,感谢您的回复!不幸的是,每个请求都使用新实例并每次都销毁它,以及防止缓存的 pragma 和 xhr 设置方法(改编自 here)都没有带来预期的效果。内存使用量仍在随时间增长,最终导致浏览器崩溃! 你为什么在你的回调代码中调用abort()?当您调用 abort 时,xhr 的状态变为 0(未初始化) - 请参阅 msdn.microsoft.com/en-us/library/ie/ms535920(v=vs.85).aspx。这种行为很可能会阻止清理 xhr 内容,因为底层系统认为从未发出过请求。我想说无论如何都不要在正常操作中使用 abort 方法,因为这会“取消”您正在发出的请求。当 hxr 超出范围时,它会有效地自行清理。仅使用它来取消正在进行的请求。让我知道这是否有帮助。 嗨,罗伯!你是对的,在这种情况下不需要调用abort()。如果请求超时,实际代码仅使用该方法。不幸的是,即使我不使用abort() 方法,内存仍在增长。但再次感谢您的帮助!

以上是关于使用定期 AJAX/XMLHttpRequest 调用时如何修复浏览器的内存增长?的主要内容,如果未能解决你的问题,请参考以下文章

AJAX XMLHttpRequest POST

原生Ajax(XMLHttpRequest)

我无法使用 AJAX (XMLHttpRequest) 获取 responseXML

使用 AJAX/XMLHttpRequest 时不调用 shouldStartLoadWithRequest

使用 Ajax XMLHttpRequest 上传文件

原生Ajax--XmlHttpRequest对象