Правильное использование ресурсов браузера
У меня есть веб-приложение, которое динамически загружает данные в течение длительного периода времени. Внутри данных есть ссылки на изображения, которые затем отображаются в браузере.
например.
var object = {
Name: ko.observable("Foo"),
Ref: ko.observable("Bar"),
ImageUrl: ko.observable("http://.....")
}
Я использую Knockoutjs привязку шаблона для отображения данных на экране.
<img data-bind="attr: { src: imageUrl }" />
Таким образом, каждый раз, когда объект изменяется с помощью вызова Ajax, шаблон Knockoutjs повторно отображается с данными, а изображения меняются.
После длительного периода времени эти изображения накапливаются и будут потреблять больше памяти. Современные браузеры, похоже, справляются лучше, но проблема в основном связана с IE8 (мы не поддерживаем < IE8). Даже в современных браузерах память в конечном итоге будет настолько высока, что браузер зависнет.
См. этот снимок экрана для примера создания ресурсов изображения.
![enter image description here]()
Я решил посмотреть, что произойдет, если вместо использования тега <img />
используйте <iframe />
.
Итак, мой код теперь выглядит как
<iframe data-bind="attr: { src: imageUrl }"></iframe>
Что происходит, так это то, что создается кадр, но как только изменяется значение imageUrl, кадр просто обновляется и не создает дополнительных ресурсов.
![enter image description here]()
![enter image description here]()
Итак, если я хочу использовать использование памяти браузера, я могу использовать эту технику <iframe />
, но мне это не нравится. Это заставляет меня делать много других изменений в приложении, плюс мне нужно использовать iframes!
Теперь я проверил различные тесты, чтобы узнать, сколько памяти используется с использованием обоих методов, и за тот же период времени память увеличится с 81 000 до 200 000 к (с <img />
) по сравнению с 81 000 к 98 000 k (с <iframe />
)
Вопрос
Есть ли лучший способ управления ресурсами изображения в браузере? Есть ли способ правильно избавиться от этого изображения?
Я искал в Интернете ответ, но до сих пор я ничего не нашел.
Edit
На самом базовом уровне. Я попытался удалить изображение с помощью метода jQuery remove()
, но ресурс изображения никогда не удаляется. См. Эту скрипку для очень простого примера. http://jsfiddle.net/ezb9e/
код:
HTML
<img src="http://www.fillmurray.com/200/300" />
JS
$(function(){
setTimeout(function(){
$('img').remove();
$('body').append($('<img />', { attr: { src: 'http://www.fillmurray.com/300/200' }}));
}, 3000);
});
Ответы
Ответ 1
Я бы попытался использовать пользовательскую привязку и создать и уничтожить изображения в этом. У меня была аналогичная проблема в прошлом году с SVG, и что я должен был сделать.
ko.bindingHandlers.createImage = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
// Use something unique to identify this image object
var imageName = viewModel.Name();
var parent = bindingContext.$parent;
var imageObject = parent.Images[imageName];
if (imageObject) {
$(element).empty()
imageObject = null;
}
imageObject = $(element).append('<img src="' + viewModel.imgSrc() + '" />')[0];
parent.Images[imageName] = imageObject;
}
};
Здесь воссоздается исходная проблема:
http://jsfiddle.net/manzanotti/ezb9e/5/
И вот моя версия:
http://jsfiddle.net/manzanotti/ezb9e/13/
Память сначала идет вверх, но время от времени происходит сбор мусора, поэтому она никогда не выходит из-под контроля. Это проверено в IE9 и Chrome.
Update Хмм, я не уверен, что это полностью устраняет проблему в IE8. Я запустил скрипку в sIEve, и память все еще продолжается, хотя, поскольку sIEve добавляет крючки в узлы DOM, это может быть результатом ее запуска в sIEve. Chrome определенно хорош, но IE9 кажется, по крайней мере, намного лучше, если не полностью исправлен.