Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 28.11.2020, 03:46
Кандидат Javascript-наук
Отправить личное сообщение для Was-Ja Посмотреть профиль Найти все сообщения от Was-Ja
 
Регистрация: 20.09.2020
Сообщений: 130

Как правильно удалить старое содержимое innerHTML перед новым присвоением?
Добрый день,

опрометчиво заложил в своей логике использование innerHTML, часто в нее пишу гремучую строку, которая содержит множество вложенных divов, а внутри них - все подряд, и канвасы, и картинки, и таблицы и евенты биндю. Заметил, что память от предыдущего содержимого не освобождается...

Погуглил, нашел и адаптировал под себя такой вариант

function ReSet_innerHTML(id, html)
{ const myNode = ID(id);
  while (myNode.firstChild) {
    myNode.removeChild(myNode.lastChild);
  }
  myNode.innerHTML=html;
}


потерь по памяти стало существенно меньше, но, память все равно теряется.

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

Если это так, пожалуйста, посоветуйте, как проще сделать правильно удаление, чтоб удалить реально все?

Спасибо!
Ответить с цитированием
  #2 (permalink)  
Старый 28.11.2020, 08:25
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,692

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

var block = document.getElementById('block')

Потом

block.remove();

или в его родительском

parent.innerHTML = "новое содержимое";

Но пока переменная block будет ссылаться на этот элемент он будет занимать место в памяти вместе со всеми своими потомками, обработчиками событий и картинками.

Последний раз редактировалось voraa, 28.11.2020 в 08:36.
Ответить с цитированием
  #3 (permalink)  
Старый 30.11.2020, 10:29
Кандидат Javascript-наук
Отправить личное сообщение для Was-Ja Посмотреть профиль Найти все сообщения от Was-Ja
 
Регистрация: 20.09.2020
Сообщений: 130

Спасибо, voraa, за ответ!

Сообщение от voraa Посмотреть сообщение
Как удалять совершенно без разницы.
Если остаются какие либо ссылки на старые элементы, то эти элементы, а так же их дочерние все равно не будут удалены из памяти...
да, верно, Вы это мне говорили и я приложил все усилия чтобы этого не было. То есть у меня все данные лежат в одном объекте, и я регулярно этот объект удаляю и записываю в него новые данные.

Грешить не на кого, я пока сторонних фреймворков не пользую.

Если занулять старое содержимое, переписывая innerHTML, то за каждый шаг теряется 2-3мбайта, если делать с удалением child как я написал выше, остается 300кбайт, но все равно остается... Из-за этого я предполагаю, что все-таки дело в способе удаления.

Код не получается выложить, я что-то с сервером накосячил (по локалке все работает, а через мой сервер - нет), если быстро пофиксю, положу и покажу когда и где это происходит.
Ответить с цитированием
  #4 (permalink)  
Старый 30.11.2020, 13:53
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,692

Ну да, способ удаления может влиять. Но все равно в памяти будут оставаться элементы, на которые есть ссылки
Вот, например, есть
<div id='cotainer'>
</div>

И вы делаете
document.getElementById('container').innerHTML = "<div id='block'><div id='ch1'>...</div><div id='ch2'>...</div></div>"

let ch1 = document.getElementById('ch1')

Потом снова
document.getElementById('container').innerHTML = "<div id='block'><div id='ch1'>...</div><div id='ch2'>...</div></div>"


Но все старое содержимое не удалится. Потому, что ch1 ссылается на свой элемент, он, через свойство parentElement ссылается на div#block, а тот ссылается на всех своих потомков. И все сидит в памяти

Если сначала удалить через remove, то в памяти останутся только div#ch1 и его потомки. И будут сидеть там, пока переменная ch1 ссылается на него.
Ответить с цитированием
  #5 (permalink)  
Старый 30.11.2020, 16:27
Кандидат Javascript-наук
Отправить личное сообщение для Was-Ja Посмотреть профиль Найти все сообщения от Was-Ja
 
Регистрация: 20.09.2020
Сообщений: 130

Спасибо большое, voraa, что помогаете!

Сообщение от voraa Посмотреть сообщение
И вы делаете
document.getElementById('container').innerHTML = "<div id='block'><div id='ch1'>...</div><div id='ch2'>...</div></div>"

let ch1 = document.getElementById('ch1')
правильно, чтобы этого избежать я кладу все эти переменные (ch1) в один единственный объект (Data.ch1, ... ), и, когда приходят новые данные с сервера, этот объект (Data) удаляю. Вернее делаю команду

Data=JSON.parse(xhr.response);

в надежде, что все старое удалиться, так как больше ссылаться не на кого. Сейчас попробовал руками удалять внутренности моего Data до присвоения

Data=JSON.parse(xhr.response);

но пока не помогло.
Ответить с цитированием
  #6 (permalink)  
Старый 30.11.2020, 17:11
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,692

И в этом объекте лежит и то, что приходит с сервера, и то, что вы получаете сами?
Ведь с сервера приходит только то, что нужно как то поместить в элементы, а сами ссылки на элементы, которые получаются по
getElementById или querySelector с сервера не приходят.
Или вы с этими элементами никак не работаете, обработчики им не назначаете, классы и стили не меняете?

Тогда есть вариант, что вы видите утечку памяти в те моменты, когда ее очистка не произошла. Это не сразу происходит. Сборщик мусора работает в какие то определенные моменты времени. И не всегда очищает все, что требует очистки за один раз.
Ответить с цитированием
  #7 (permalink)  
Старый 30.11.2020, 21:00
Кандидат Javascript-наук
Отправить личное сообщение для Was-Ja Посмотреть профиль Найти все сообщения от Was-Ja
 
Регистрация: 20.09.2020
Сообщений: 130

Спасибо большое, voraa, за содействие!

Сообщение от voraa Посмотреть сообщение
И в этом объекте лежит и то, что приходит с сервера, и то, что вы получаете сами?
да, именно так. Я пошел на такое извращение, чтобы проще удалять ссылки и гарантировать (по крайней мере себе) что все с предыдущего шага удалено.

Сообщение от voraa Посмотреть сообщение
Тогда есть вариант, что вы видите утечку памяти в те моменты, когда ее очистка не произошла. Это не сразу происходит. Сборщик мусора работает в какие то определенные моменты времени. И не всегда очищает все, что требует очистки за один раз.
какой-то кривой, похоже, в файерфоксе сборщик мусора.

У меня примерно раз в 10 секунд приходит новый комплект данных (не всегда так часто, но есть режимы, когда такое происходит).

Пришедших данных с сервера не много, около сотни килобайт. Из них я рисую с десяток канвасов и биндю на канвасы евенты, связанные с отрисовкой. В канвасах нарисованы 3Д модели молекул, мышкой их можно повертеть и включить/выключить отрисовку, например, водородов.

Гружу все всегда в один и тот же объект. В нем завожу всегда несколько дополнительных объектов, в основном матрицы поворотов-трансформаций и какие-то включатели-выключатели. Ни одного названия div явно в этой структуре не храню.

Названия div всегда имеют какой-то смысл, типа "MolFrame_"+Index, где Index - это номер молекулы. По таким названиям я и генерю ссылки, когда срабатывает евент и мне надо что-то в канвасе перерисовать.

Еще одновременно с этим перерисовывается панель с кнопками (картинки загружаются из локальных копий, которые сохранены в виде текста "data:image/png;base64,iVBOR..."

По приходе нового комплекта данных с сервера вся эта ботва полностью перерисовывается.

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



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
innerHTML как правильно вставить текст ? lamer Общие вопросы Javascript 8 05.06.2016 04:25
Как правильно реализовать такой функционал? Julian Общие вопросы Javascript 3 16.01.2015 12:34
Как правильно спроектировать приложение? Alex Danilov ExtJS 7 22.05.2012 19:00
Как правильно удалить из шаблона, javascript код? QroxZ Общие вопросы Javascript 0 04.11.2011 17:59
Как правильно послать XML в POST запросе LowCoder AJAX и COMET 10 15.07.2009 23:20