Можно ли использовать iframe в IE без утечек памяти? - PullRequest
24 голосов
/ 07 декабря 2011

Все версии IE (включая 10), по-видимому, удерживают значительный объем памяти, выделяемый фреймами, до появления window.top.unload. Это создает серьезную проблему для долгоживущих страниц, которые могут создавать множество фреймов в течение всей жизни. Упрощенный пример проблемы можно найти здесь:

http://pastebin.com/FmZ7iMHB

Этот пример использует страницу Википедии для iframe, чтобы увеличить проблему, но даже простая страница с одним изображением будет утечка.

В двух словах: после уничтожения iframe в IE вы получаете часть, но не всю память обратно, когда в следующий раз страница запускает сборку мусора (обычно около 25% памяти, используемой iframe, застревает в подвешенном состоянии) , Обновление или переход на новую страницу (window.top.unload) освободит большую часть или всю оставшуюся память.

Эта конкретная утечка не обнаруживается в таких инструментах, как sIEve и Microsoft JS Memory Leak Detector . Я прочитал все, что могу найти об утечках iframe в IE, но мне не повезло с решениями, с которыми я столкнулся.

Кто-нибудь знает решение или способ решения этой проблемы? Единственная стратегия смягчения, которая у меня есть, - это сделать как можно больше очистки из iframe до того, как родительская страница уничтожит его, но это не поможет, если вы не контролируете страницу, в которую вставлена ​​рамка.

Ответы [ 3 ]

8 голосов
/ 17 июля 2012

Я собрал плагин 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().

Как указывает Джош, фреймы, отображающие изображение, похоже, связаны с утечками памяти.Например, создание фреймов, указывающих на google.com , приведет к утечке памяти в IE7 и IE8.Использование описанного выше плагина предотвращает эти утечки.

К сожалению, этот плагин работает не во всех случаях.Похоже, что это не очень помогает с iframes, указанными на // en.wikipedia.org/wiki/Memory_leak.

Код, который я использовал для тестирования утечек памяти и для тестирования вышеупомянутого плагинанаходится в https://gist.github.com/3125807

Как говорит Джош, утечки памяти в IE8 на самом деле являются псевдо-утечками.Однако в IE7 память не освобождается, даже когда родительское окно выгружается.

2 голосов
/ 23 апреля 2015

В IE 11 просто установка iframe.src = 'about:blank', кажется, исправляет это.В противном случае вы можете наблюдать, как память постоянно растет на вкладке Память F12, даже если вы удаляете фреймы из DOM и позволяете им собирать мусор.Если вы сначала очистите кадры, вы увидите, что память идет вверх и вниз, как и следовало ожидать.

0 голосов
/ 27 декабря 2013

Попробуйте с этим:

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();
      }
    }
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...