【问题标题】:Is it possible to use iframes in IE without memory leaks?是否可以在没有内存泄漏的情况下在 IE 中使用 iframe?
【发布时间】:2011-12-06 22:41:01
【问题描述】:

所有版本的 IE(包括 10 个)似乎都保留了 iframe 分配的大量内存,直到 window.top.unload 发生。这对于可能会在其整个生命周期中创建许多 iframe 的长期页面来说是一个相当大的挑战。可以在此处找到该问题的简化示例:

http://pastebin.com/FmZ7iMHB

该示例使用 iframe 的 Wikipedia 页面来放大问题,但即使是带有单个图像的简单页面也会泄漏。

简而言之,在 IE 中销毁 iframe 后,下次页面触发垃圾回收时,您会获得一些但不是全部的内存(通常大约 25% 的 iframe 使用的内存会陷入困境) .刷新或导航到新页面 (window.top.unload) 将释放大部分或全部剩余内存。

在 sIEve 和 Microsoft 的 JS Memory Leak Detector 等工具中无法检测到这种特殊的泄漏。我已经阅读了我能找到的关于 IE 中泄漏 iframe 的所有内容,但我遇到的解决方案没有运气。

有人知道这个问题的解决方案或解决方法吗?我唯一的缓解策略是在父页面销毁 iframe 之前尽可能多地在 iframe 中进行清理,但是当您不控制被框入的页面时,这无济于事。

【问题讨论】:

  • 会不会只是缓存?许多浏览器将图像等保存在内存中,因此下次需要时不必重新下载它们。如果真的存在内存泄漏,微软现在应该已经修复了。
  • 从技术上讲,我相信这是"pseudo-leak",这意味着丢失的内存在父页面卸载时被回收,并且实际上并没有永远丢失。然而,正如上面的链接所提到的,这对于长期存在的页面来说仍然是一个问题(想想 Pandora 或基于 Web 的监控工具,您可能会让页面保持打开数小时)。不幸的是,所提供的解决方案在这种情况下没有效果。
  • 我不认为缓存是一个因素(虽然我肯定是错的),因为通过 F12 开发人员工具禁用浏览器缓存似乎没有效果,并且加载一个简单的页面重复使用相同的图像会泄漏。
  • 乔希,你在这个主题下有什么消息吗?
  • @Castanho 我不认为这是可以修复的,但绝对可以缓解。如果您有长期存在的页面和大量 IE 访问者,您应该尽一切可能避免加载大文件的 iframe。出现此问题的典型罪魁祸首是轮播广告,它会一遍又一遍地创建带有图像或 Flash 内容的 iframe,每次都会泄漏少量内存,而且会慢慢增加。

标签: internet-explorer iframe memory-leaks


【解决方案1】:

我整理了一个用于清理 iframe 的 jQuery 插件,在某些情况下可以防止内存泄漏:

(function($) {
    $.fn.purgeFrame = function() {
        var deferred;

        if ($.browser.msie && parseFloat($.browser.version, 10) < 9) {
            deferred = purge(this);
        } else {
            this.remove();
            deferred = $.Deferred();
            deferred.resolve();
        }

        return deferred;
    };

    function purge($frame) {
        var sem = $frame.length
          , deferred = $.Deferred();

        $frame.load(function() {
            var frame = this;
            frame.contentWindow.document.innerHTML = '';

            sem -= 1;
            if (sem <= 0) {
                $frame.remove();
                deferred.resolve();
            }
        });
        $frame.attr('src', 'about:blank');

        if ($frame.length === 0) {
            deferred.resolve();
        }

        return deferred.promise();
    }
})(jQuery);

此代码通过在清理其内容之前将帧 src 更新为“about:blank”来处理跨域帧。要使用该插件,请致电$frame.purgeFrame(),否则您将致电$frame.remove()。

正如 Josh 所指出的,显示图像的 iframe 似乎与内存泄漏有关。例如,创建指向google.com 的 iframe 将在 IE7 和 IE8 中产生内存泄漏。使用上面的插件可以防止这些泄漏。

不幸的是,该插件并非在所有情况下都有效。指向//en.wikipedia.org/wiki/Memory_leak 的 iframe 似乎没有多大帮助。

我用于测试内存泄漏和测试上述插件的代码位于https://gist.github.com/3125807

正如 Josh 所说,内存泄漏实际上是 IE8 中的伪泄漏。但是在 IE7 中,即使父窗口卸载,内存也不会被回收。

【讨论】:

    【解决方案2】:

    在 IE 11 中,仅设置 iframe.src = 'about:blank' 似乎可以解决此问题。否则,您可以在 F12 内存选项卡中看到内存永远增长,即使您正在从 DOM 中删除 iframe 并让它们被垃圾回收。如果您先将 iframe 清空,您会看到内存按预期上升和下降。

    【讨论】:

      【解决方案3】:

      试试这个:

      collectGarbageForIframe: function() {
        var $iframes = $("*[tag='iframe']");
        $iframes.each(function() {
          var $target = $(this);
          if($target.length>0) {
            $target[0].src = "about:blank";
            $target[0].contentWindow.document.write('');
            $target[0].contentWindow.close();
            $target.remove();
            if( typeof CollectGarbage == "function") {
              CollectGarbage();
            }
          }
        });
      }
      

      【讨论】:

        【解决方案4】:

        您遗漏了一个重要步骤: 将 src 设置为 'about:blank' 后,您需要监听 'about:blank' 的负载,然后才删除您的 iFrame。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-19
          • 1970-01-01
          • 1970-01-01
          • 2017-05-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多