Подтвердить что ты не робот

Можно ли использовать iframes в IE без утечек памяти?

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

http://pastebin.com/FmZ7iMHB

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

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

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

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

4b9b3361

Ответ 1

Я собрал плагин jQuery для очистки iframe, который предотвращает утечку памяти в некоторых случаях:

(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().

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

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

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

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

Ответ 2

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

Ответ 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.