Как правильно удалить старое содержимое innerHTML перед новым присвоением?
Добрый день,
опрометчиво заложил в своей логике использование innerHTML, часто в нее пишу гремучую строку, которая содержит множество вложенных divов, а внутри них - все подряд, и канвасы, и картинки, и таблицы и евенты биндю. Заметил, что память от предыдущего содержимого не освобождается... Погуглил, нашел и адаптировал под себя такой вариант function ReSet_innerHTML(id, html) { const myNode = ID(id); while (myNode.firstChild) { myNode.removeChild(myNode.lastChild); } myNode.innerHTML=html; } потерь по памяти стало существенно меньше, но, память все равно теряется. Скажите, пожалуйста, правильно ли я понимаю, что мой способ не удаляет евенты, которые там были забиндены и картинки, которые там были вставлены? Если это так, пожалуйста, посоветуйте, как проще сделать правильно удаление, чтоб удалить реально все? Спасибо! |
Как удалять совершенно без разницы.
Если остаются какие либо ссылки на старые элементы, то эти элементы, а так же их дочерние все равно не будут удалены из памяти. Например, где то вы сделали var block = document.getElementById('block') Потом block.remove(); или в его родительском parent.innerHTML = "новое содержимое"; Но пока переменная block будет ссылаться на этот элемент он будет занимать место в памяти вместе со всеми своими потомками, обработчиками событий и картинками. |
Спасибо, voraa, за ответ!
Цитата:
Грешить не на кого, я пока сторонних фреймворков не пользую. Если занулять старое содержимое, переписывая innerHTML, то за каждый шаг теряется 2-3мбайта, если делать с удалением child как я написал выше, остается 300кбайт, но все равно остается... Из-за этого я предполагаю, что все-таки дело в способе удаления. Код не получается выложить, я что-то с сервером накосячил (по локалке все работает, а через мой сервер - нет), если быстро пофиксю, положу и покажу когда и где это происходит. |
Ну да, способ удаления может влиять. Но все равно в памяти будут оставаться элементы, на которые есть ссылки
Вот, например, есть <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 ссылается на него. |
Спасибо большое, voraa, что помогаете!
Цитата:
Data=JSON.parse(xhr.response); в надежде, что все старое удалиться, так как больше ссылаться не на кого. Сейчас попробовал руками удалять внутренности моего Data до присвоения Data=JSON.parse(xhr.response); но пока не помогло. |
И в этом объекте лежит и то, что приходит с сервера, и то, что вы получаете сами?
Ведь с сервера приходит только то, что нужно как то поместить в элементы, а сами ссылки на элементы, которые получаются по getElementById или querySelector с сервера не приходят. Или вы с этими элементами никак не работаете, обработчики им не назначаете, классы и стили не меняете? Тогда есть вариант, что вы видите утечку памяти в те моменты, когда ее очистка не произошла. Это не сразу происходит. Сборщик мусора работает в какие то определенные моменты времени. И не всегда очищает все, что требует очистки за один раз. |
Спасибо большое, voraa, за содействие!
Цитата:
Цитата:
У меня примерно раз в 10 секунд приходит новый комплект данных (не всегда так часто, но есть режимы, когда такое происходит). Пришедших данных с сервера не много, около сотни килобайт. Из них я рисую с десяток канвасов и биндю на канвасы евенты, связанные с отрисовкой. В канвасах нарисованы 3Д модели молекул, мышкой их можно повертеть и включить/выключить отрисовку, например, водородов. Гружу все всегда в один и тот же объект. В нем завожу всегда несколько дополнительных объектов, в основном матрицы поворотов-трансформаций и какие-то включатели-выключатели. Ни одного названия div явно в этой структуре не храню. Названия div всегда имеют какой-то смысл, типа "MolFrame_"+Index, где Index - это номер молекулы. По таким названиям я и генерю ссылки, когда срабатывает евент и мне надо что-то в канвасе перерисовать. Еще одновременно с этим перерисовывается панель с кнопками (картинки загружаются из локальных копий, которые сохранены в виде текста "data:image/png;base64,iVBOR..." По приходе нового комплекта данных с сервера вся эта ботва полностью перерисовывается. Так вот я прождал больше часа, тыкаясь после каждой такой перерисовки в снапшот, занятость памяти всегда росла, и даже число используемых картинок все время только росло, хотя у меня только 10 таких встроенных картинок всего. То есть я ни разу не заметил, как сборщик мусора сработал и это меня понятно очень напрягло. |
Часовой пояс GMT +3, время: 09:35. |