IE中的内存泄漏:由于使用.load()调用ajax

时间:2014-07-21 18:11:30

标签: javascript performance internet-explorer memory-leaks html-components

我通过ajax调用在div中加载.html文件的全部数据。 html页面包含 HTC (html组件)与页面上的元素绑定所需的链接,脚本标记。

页面的结构如下:

enter image description here 我正在使用jQuery来加载像这样的HTML页面

<body>
<input type="radio" class="openpage" id="0001">
<input type="radio" class="openpage" id="0002">
<input type="radio" class="openpage" id="0003">
<input type="radio" class="openpage" id="0004">

<div id="loadPage"></div>
<script>
$(document).ready(function(){
  $(".openpage").on("click",function(){
    $("#loadPage").load($(this).attr("id")+".html",function(){
    //load a page with many htc bindings and external references

    //trigger some onload functions which are not called automatically in IE
    //confirmed this is in chrome

    });
  });
})
</script>

</body>

问题在于IE内存不断增加,因为点击单选按钮加载页面,加载几页后浏览器停止响应。 我可以在任务管理器中看到内存。

该应用程序在IE 5,6,7,8,9中运行,在IE10中以怪癖模式运行。我尝试在chrome中复制相同的场景,但没有显示任何问题。所以我认为这是IE特定的内存管理相关问题。

我阅读了很多文章,但我不相信。我也在SO上阅读了this的问题,但是它建议只加载一些在我的案例中不可接受的页面部分。这article似乎是相关的但我不确定在我的情况下究竟是什么导致内存泄漏。

上面的整个实体都是iframe 。所以作为一种解决方法,我重新加载 8页单击单选按钮后包含主页面的框架。 我试图在每次加载之前清除东西:

$("#loadPages").empty();

$("#loadPages").find("*").off();

$.ajaxSetup({ cache: false });

但没有任何作用。所以我怀疑jquery是否可以清除通过htc注册的事件。

1)如果你在这种情况下解释内存泄漏的原因会很棒。

2)一般情况下,为什么在加载许多资源后,浏览器会发生内存泄漏。这在现代浏览器中不会发生,但为什么它出现在旧浏览器中。

3)有没有办法在不刷新帧的情况下释放浏览器内存。

4)有没有办法检查所有资源都存在于浏览器内存中。

2 个答案:

答案 0 :(得分:4)

您有几个工作流程:

  • 用动态加载的结构替换现有的DOM结构。
  • 加载后连接其他事件处理。

从这里开始:

  • 删除/替换DOM节点时,仍会绑定事件
  • 通过绑定到事件处理程序,DOM节点可能无法清除
  • DOM节点在内存中保留,与UI分离,但仍然在泄漏内存。

您的选择是:

  • 在从DOM中清除这些节点并允许加载新内容之前,确保清除现有结构上的所有事件。
  • 有几个节点可供显示,并且每个节点只加载一次。
  • 检查节点是否存在,只需将其分离,而不是尝试替换它。

IE为JavaScript和Rendering引擎提供了单独的COM通道,这有时意味着,特别是对于事件绑定。 JS中的对象/状态可以保持对UI / DOM节点的引用......并且DOM节点可以引用JS事件处理程序。在许多情况下,这意味着这些部分不会被垃圾收集,从而导致内存使用量增加。早期版本的情况要糟糕得多,但仍然会发生。

您可能会遇到与其他浏览器类似的问题,但IE往往会更快地显示此行为。对于长期存在的单页应用程序,情况也会更多。

如果您只将每个资源加载到其自己的DOM节点中,则可以简单地分离/重新连接该节点。此外,您可以依靠事件传播来侦听来自父节点的事件。这些都可以降低争用风险和开销。

对于取消注册事件处理程序,只要您使用jQuery注册,并使用jQuery删除/删除节点(及其子节点),jQuery就可以比大多数人更好地工作。

答案 1 :(得分:1)

你有没有考虑过使用xhr请求? 他们可以使用ajax将内容加载到目标。 我为你的问题做了一个示例小提琴。看看它。 欢呼声。

&#13;
&#13;
function getXmlHttpRequest() {
  var xmlhttp;
  if (window.XMLHttpRequest) {
    xmlhttp = new XMLHttpRequest();
    // code for IE7+, Firefox, Chrome, Opera, Safari

  } else if (window.ActiveXObject) {
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    // code for IE5 and IE6
  } else {
    alert("Browser doesn't support Ajax..!!");
  }

  return xmlhttp;
}

function loadPage(pageTitle) {
  //pageTitle = pageTitle + ".html";
  xmlhttp = getXmlHttpRequest();
  if (xmlhttp != null) {
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState < 4) {
        document.getElementById('loadPage').innerHTML = "Content Loading...!";
      } else if (xmlhttp.readyState == 4) {
        var res = xmlhttp.responseText;
        document.getElementById('loadPage').innerHTML = res;
      }
    }
    xmlhttp.open("GET", pageTitle, true);
    xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xmlhttp.send(null);
  }
}

function showAlert() {
  alert("This is me!");
}
$(document).ready(function() {
  $(".openpage").on("click", function() {
    loadPage($(this).attr("id"));
  });
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<input type="radio" class="openpage" name="radio-group" id="https://dl.dropboxusercontent.com/u/105580681/xhr-fiddle/0001.html">
<input type="radio" class="openpage" name="radio-group" id="https://dl.dropboxusercontent.com/u/105580681/xhr-fiddle/0002.html">
<input type="radio" class="openpage" name="radio-group" id="https://dl.dropboxusercontent.com/u/105580681/xhr-fiddle/0003.html">
<input type="radio" class="openpage" name="radio-group" id="https://dl.dropboxusercontent.com/u/105580681/xhr-fiddle/0004.html">
<div id="loadPage"></div>
&#13;
&#13;
&#13;

在这个小提琴中,我使用Dropbox链接加载html文件。您可以使用0001 - 0004 id号的初始概念。
但是,如果要加载html页面的整个内容,这将加载从外部html页面到目标主页面内部的所有内容。

例如:

<div id="loadPage">
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <div>Content of HTML 0001 Page</div>
</div>

这会影响主页面的DOM文件。页面功能不会松动,但它不是一个好的编程技术。因此,您可能需要在要在目标元素上显示的xxxx.html文件中编写或加载内容。

了解更多信息 Using XMLHttpRequest Mozilla MDN
Using FormData Objects Mozilla MDN