【问题标题】:jQuery load() method memory leak?jQuery load() 方法内存泄漏?
【发布时间】:2011-01-10 20:15:47
【问题描述】:

我一直在寻找这个问题的答案,虽然找到了相关的问题,但我找不到完全匹配的问题。

我有一个相当大的应用程序,它应该使用 jQuery.load() 方法将页面加载到另一个页面的 div 中。我遇到的问题是,当一次又一次地将同一个页面加载到同一个 div 中时,我看到浏览器的内存大幅增加(内存泄漏)。如果我调用 $("*").unbind,我当然看不到泄漏,但是一切都已重置,所以这并不是真正的修复。下面的代码示例重现了这个问题:

Test1.htm

<head>
   <title></title>
    <script type="text/javascript" language="javascript" src="Scripts/jquery-1.3.2.js"></script>
        <script type="text/javascript" language="javascript">
        <!--
            var i = 0;
        $(document).ready(function() {
            $("#btn").click(
                function() {
                    i++;
                    $("#Test1").load("Test2.htm", null, function() {
                        //$(document).trigger("test");
                    })
                    $("#count").html(i);
                });
        });
    //-->
    </script>
</head>
<body>
    <img id="btn" src="someimage.png" />
    <h3>We are loading Test2.htm into below div</h3>
    <div>
        Count loads =<span id="count">0</span>
    </div>
    <div id="Test1" style="border-style:solid">EMPTY</div>
</body>

Test2.htm = 任何旧的 html 页面..

如果您加载 Test1.htm 并多次单击按钮,您会注意到浏览器内存稳步增加。我认为问题在于加载的 js 和 DOM 元素从未设置为垃圾收集。在我的现实世界系统中,我尝试删除 (elem.remove() 或 .empty()) 加载的元素,但这并不能真正解决问题。我还使用“src”加载了许多 js 文件,我将其替换为 $.getScript,这似乎有了一个小的改进。这些都是想到的解决方法,我想为这个问题找到一个真正的解决方案。有什么想法吗?

【问题讨论】:

  • Test2.htm中有js代码吗?您是否在任何其他函数中引用了以load() 加载的对象?如果您将使用普通的$.ajax() 调用加载数据,内存泄漏会持续吗?

标签: javascript jquery internet-explorer memory-leaks


【解决方案1】:

编辑:由于提供了有关 test2.htm(正在加载的页面)的更多信息而更新

原始答案(出于历史目的):我实际上没有在您提供的代码/标记中看到任何泄漏 - 泄漏是否可能在 Test2.htm 中(您没有提供代码/标记)?

新答案:

我建议这可能是由于多次加载 jQuery 或您在 test2.htm 中拥有的其他脚本。

假设 jQuery 不会通过简单地实例化然后使 jQuery$ 无效而泄漏,多次加载将在内存中保留至少 2 个 jQuery 副本。加载时,jQuery 会在 _$_jQuery 中保留 $jQuery 的任何先前版本的备份 - 因此,当您多次使用 load() 时,您将至少加载 2 个 jQuery 副本。

上述假设很可能正确但是 - 即使您通过设置 $,jQuery,_$ 和 @ “卸载”它,jQuery 也很有可能会泄漏987654330@ 到 null - 它并不是真的打算像那样多次加载(但我确信他们是故意允许的,所以如果需要,您可以使用 noConflict() 加载和使用两个不同版本的 jQuery)。

您可以将“选择器”添加到加载 URL。例如:

$("#Test1").load("Test2.htm body", null, function() { 
  //callback does nothing
});
//or
$("#Test1").load("Test2.htm div#the_Div_I_Want", null, function() { 
  //callback does nothing
});

如果您对 ajax 结果中的任何脚本不感兴趣,或者如果您确实想要脚本,我建议您这样做,您需要选择一个选择器来仅禁用某些元素/脚本,例如

/* load with selector "all elements except scripts whose
   src attribute ends in 'jquery.js'" */
$("#Test1").load("Test2.htm :not(script[src$='jquery.js'])", null, function() { 
  //callback does nothing
});

另外值得注意的是,如果你省略了“数据”参数(你有它作为null),并提供一个函数作为第二个参数,jQuery 将正确地确定第二个参数是回调,所以

$("#Test1").load("Test2.htm :not(script[src$='jquery.js'])", function() { 
  //callback does nothing
});

可以接受

【讨论】:

  • 我刚刚在 Test2.htm 中尝试了以下代码:
    TEST NOTHING
    这仍然会导致 IE8 中的泄漏,但不会在 Firefox 中(或者它太小而无法注意到)。但是,更复杂的 Test2.htm 仍然会导致 Firefox 泄漏。只需复制 Test1.htm 并删除脚本块和图像,就会出现问题。但是,我在这个子页面中有一个对 jquery 库的引用,如果我删除它,那么泄漏就不会那么明显了。似乎 jquery 库在加载 Test2.htm 时被缓存,然后从未被清除。
  • 根据您提供的信息编辑答案 - 希望对您有所帮助
【解决方案2】:

嗯,也许这只是一些非常基本的东西,但如果我设置 $.ajaxSetup({ cache: false });在负载调用之前,我似乎没有得到问题。现在,我的“真实”代码当然有这个调用,那么为什么我会看到问题呢?我相信 Tabs UI 扩展会导致缓存被打开(我实际上并不相信这一点,但在每次加载之前调用错误的缓存调用似乎可以解决它!)

【讨论】:

    【解决方案3】:

    好的,所以我终于找到了问题,它根本不是泄漏(我怀疑),它只是将多个非常复杂的处理程序附加到同一个触发器/事件的结果。我提出了与此相关的问题:

    JQuery event model and preventing duplicate handlers

    【讨论】:

      猜你喜欢
      • 2012-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-20
      相关资源
      最近更新 更多