утечка памяти jQuery с удалением DOM

Удостоверьтесь, что получили все "глюки" для приложения. Они часто - данные или бизнес-объекты, которые являются также минутой или изворотливый, чтобы иметь официальную документацию, но завершить имеющее большое влияние или много времени отладки, если Вы не знаете то, что продолжается.

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

46
задан Eli Courtwright 23 September 2009 в 14:23
поделиться

4 ответа

Я подумал, что Дэвид может быть замешан в предполагаемой утечке removeChild, но я не могу воспроизвести это в IE8 ... это вполне может произойти в более ранних версиях браузеров, но это не то, что у нас здесь . Если я вручную removeChild, то утечки не будет; если я изменю jQuery на использование outerHTML = '' (или move-to-bin, за которым следует bin.innerHTML) вместо removeChild, все равно будет утечка.

В процессе устранения я начал взламывать биты удаляют в jQuery. строка 1244 в 1.3.2:

//jQuery.event.remove(this);
jQuery.removeData(this);

Комментирование этой строки не привело к утечке.

Итак, давайте посмотрим на event.remove, он вызывает data ('events') , чтобы проверить, есть ли любые события, связанные с элементом. Что делают данные ?

// Compute a unique ID for the element
if ( !id )
    id = elem[ expando ] = ++uuid;

О. Итак, он добавляет один из jQuery ' s свойства взлома uuid-to-data-lookup entry для каждого элемента, который он даже пытается прочитать данные, включая каждого потомка элемента, который вы удаляете! Как глупо. Я могу сократить это, поместив эту строку непосредственно перед ним:

// Don't create ID/lookup if we're only reading non-present data
if (!id && data===undefined)
    return undefined;

, которая, кажется, исправляет утечку для этого случая в IE8. Не могу гарантировать, что это не сломает что-то еще в лабиринте, то есть jQuery, но логически это имеет смысл.

Насколько я могу понять, утечка - это просто объект jQuery.cache (который является хранилищем данных, а не кешем как таковым) становится все больше и больше по мере добавления нового ключа для каждого удаленного элемента. Хотя removeData должен успешно удалять эти записи кэша, IE, похоже, не восстанавливает пространство, когда вы удаляете ключ из объекта.

(В любом случае, это пример поведения jQuery, которое мне не нравится. Под капотом он делает слишком много для того, что должно быть тривиально простой операцией ... некоторые из которых довольно сомнительны. Все, что связано с expando и , что jQuery делает с innerHTML через регулярное выражение, чтобы предотвратить отображение этого атрибута в IE , просто некрасиво и некрасиво. А привычка делать геттер и сеттер одной и той же функцией сбивает с толку и здесь приводит к ошибке.)

Все, что связано с расширением и , что jQuery делает с innerHTML через регулярное выражение, чтобы предотвратить отображение этого атрибута в IE , просто некрасиво и некрасиво. А привычка делать геттер и сеттер одной и той же функцией сбивает с толку и здесь приводит к ошибке.)

Все, что связано с expando и , что jQuery делает с innerHTML через регулярное выражение, чтобы предотвратить отображение этого атрибута в IE , просто некрасиво и некрасиво. А привычка делать геттер и сеттер одной и той же функцией сбивает с толку и здесь приводит к ошибке.)

[Как ни странно, оставление утечки на длительные периоды времени в конечном итоге иногда приводило к полностью ложным ошибкам в jquery.js до того, как память фактически исчерпывалась ... было что-то вроде «неожиданной команды», и я заметил, что «имя узла null или не объект »в строке 667, который, насколько я вижу, не должен был даже запускаться, не говоря уже о том, что там есть проверка на то, что nodeName имеет значение null! IE здесь не дает мне особого доверия ...]

58
ответ дан 26 November 2019 в 20:33
поделиться

See the jQuery 1.4 roadmap at http://docs.jquery.com/JQuery_1.4_Roadmap. Specifically, the section "Use .outerHTML to cleanup after .remove()" deals with memory leak issues occurring in IE due to the remove function being called.

Perhaps your issues will be resolved with the next release.

2
ответ дан 26 November 2019 в 20:33
поделиться

Does it still leak if you call empty instead of remove?

$("#content").empty();
1
ответ дан 26 November 2019 в 20:33
поделиться

Удаление элемента - это внутренняя проблема DOM. Которая останется с нами. Тоже.

jQuery.fn.flush = function()
/// <summary>
/// $().flush() re-makes the current element stack inside $() 
/// thus flushing-out the non-referenced elements
/// left inside after numerous remove's, append's etc ...
/// </summary>
{ return jQuery(this.context).find(this.selector); }

Вместо взлома jQ я использую это расширение. Особенно на страницах с множеством remove () и clones ():

$exact = $("whatever").append("complex html").remove().flush().clone();

А также помогает следующая:

// remove all event bindings , 
// and the jQ data made for jQ event handling
jQuery.unbindall = function () { jQuery('*').unbind(); }
//
$(document).unload(function() { 
  jQuery.unbindall();
});
4
ответ дан 26 November 2019 в 20:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: