2008-12-03 3 views
8

У меня есть веб-страница, которая использует jquery для получения информации о продукте, поскольку люди смотрят на вещи, а затем отображает изображения последних продуктов, которые были замечены. Это в JQuery AJAX функции обратного вызова, которая выглядит очень похоже на это:Javascript + IMG tags = утечка памяти. Есть лучший способ сделать это?

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

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

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

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

Я добавил

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

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

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

+0

Вам удалось найти утечку? Мне было бы интересно, если бы вы это сделали. – Tomalak 2008-12-08 17:58:34

+0

Нет. Он все еще течет, как сумасшедший. Я сделал другую версию приложения, которая имеет значительно отличающийся механизм отображения, но я все еще вижу, как происходит утечка изображений. – Dustin 2008-12-09 03:16:01

+0

Когда вы пишете тестовый пример, скажем, один тег img и цикл JavaScript, который заменяет его атрибут src из кучи URL-адресов (без JS-фреймворка, просто большой статический массив URL-адресов и трехстрочный цикл) - все равно утечка? Если это так, вам не повезло, если не все это можно исправить. – Tomalak 2008-12-09 10:48:09

ответ

1

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

//not tested 

var $list=$('#shots>li'); 
$list.filter(':last-child').children('img') 
.attr('src', p.ProductImageSmall) 
.parent() 
.insertBefore($list.eq(0)); 
+0

Мне нравится код, к которому это предложение привело, но изображения, похоже, не уходят. – Dustin 2008-12-03 07:32:19

+0

Дастин, когда вы говорите, что изображения не исчезают, вы можете уточнить? Вы имеете в виду, что он не меняет изображения? – redsquare 2008-12-03 08:05:22

0

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

1

Из Mozilla Developer Center on 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]); 
} 
0

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

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

0

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

http://pastebin.me/4936519fea2cf

1

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

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

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

2

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

window.setTimeout("location.reload()",1000*60*60);//refresh in an hour 
0

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

Это можно обойти путем перемещения изображения в 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'); 

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