Javascript + теги IMG = утечка памяти. Есть лучший способ сделать это? - PullRequest
8 голосов
/ 03 декабря 2008

У меня есть веб-страница, которая использует jquery для получения информации о продукте, когда люди смотрят на вещи, а затем отображают последние изображения продуктов, которые были замечены. Это обратный вызов jquery AJAX, который выглядит примерно так:

if(number_of_things_seen > 10) {
  $('#shots li:last-child').remove();
}

$('<li><img src="' + p.ProductImageSmall + '"></li>').prependTo('#shots');

Тем не менее, кажется, что утечка довольно большой памяти. Визуально это делает правильно, но след растет бесконечно.

Инспектор Safari по DOM показывает, что DOM - это то, как я и ожидал, но, похоже, он поддерживает ссылки на каждое отображаемое изображение (как видно на на этом скриншоте на случай, если кому-то это интересно).

Я добавил

$('#shots li:last-child img').remove();

к заявлению об удалении без видимого эффекта.

Есть ли какая-то магия, необходимая, чтобы позволить браузеру выпустить некоторые из этих вещей?

Ответы [ 8 ]

2 голосов
/ 13 мая 2009

Браузеры печально известны утечками памяти. Похоже, проблема возникает, когда страница остается в течение длительного времени. Как насчет обновления страницы до того, как ей не хватит памяти?

window.setTimeout("location.reload()",1000*60*60);//refresh in an hour
1 голос
/ 12 мая 2009

Является ли след действительно проблемой?

Я подозреваю, что Safari кэширует все изображения, пока вы остаетесь на том же сайте, и с этим ничего нельзя поделать. Если вам повезет, Safari выпускает ненужные объекты после достижения определенного лимита.

Причина такого поведения заключается в том, что Safari считает, что эти изображения могут быть использованы повторно, и поэтому он их кэширует.

1 голос
/ 03 декабря 2008

Из Центра разработчиков Mozilla на removeChild():

Удаленный дочерний узел все еще существует в памяти, но больше не является частью DOM. Вы можете повторно использовать удаленный узел позже в своем коде через ссылку на объект oldChild.

Это ключ - повторно использовать удаленного потомка, вместо того, чтобы повторно создавать нового.

// I'm sure there is a nicer way to do it in jQuery
if(number_of_things_seen > 10) {
  var shots = document.getElementById("shots");
  var li    = shots.getElementsByTagName("LI");
  var move  = shots.removeChild(li[li.length-1]);
  move.getElementsByTagName("IMG")[0].src = p.ProductImageSmall;
  shots.insertBefore(move, li[0]);
}
1 голос
/ 03 декабря 2008

Можете ли вы попробовать изменить src последнего ребенка и посмотреть, если это изменит? Затем вы можете переместить этот элемент, чтобы стать первым потомком

//not tested

var $list=$('#shots>li');
$list.filter(':last-child').children('img')
.attr('src', p.ProductImageSmall)
.parent()
.insertBefore( $list.eq(0) );
0 голосов
/ 06 февраля 2014

Как я недавно обнаружил, в Firefox есть ошибка, которая приводит к утечке потерянных тегов IMG.

Это можно обойти, переместив изображения в CSS:

if(number_of_things_seen > 10) {
  $('#shots li:last-child').remove();
}

$('<li><div style="background-image: url(\'' + p.ProductImageSmall +
     '\'); background-repeat: no-repeat; background-position: center; '+
     ' width: 20px; height: 20px"></div></li>').prependTo('#shots');

Проверьте, устраняет ли это утечку памяти.

0 голосов
/ 03 декабря 2008

Дастин, Кажется, оператор insertBefore в моем коде вызывал некоторые проблемы. Если вы видите этот дальнейший тестовый случай, использование памяти остается довольно статичным, хотя я очищаю последнего потомка и вставляю новый новый фрагмент dom. Работает лучше, чем последняя попытка.

http://pastebin.me/4936519fea2cf

0 голосов
/ 03 декабря 2008

хорошо, я построил для этого тестовый комплект, он случайным образом захватывает новое изображение и использует мой код замены src

см. http://pastebin.me/4936458820c43

0 голосов
/ 03 декабря 2008

как долго вы наблюдаете это «бесконечно растущее»? некоторые реализации сборщиков мусора не обязательно возвращают память операционной системе так быстро, если это вообще происходит. Можете ли вы перевести то, что вы пытаетесь сделать, в настоящий простой тест (например, установить src изображения снова и снова) без ajax или обратных вызовов? Есть ли у вас / вы можете попробовать это с другими браузерами?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...