Некоторое время искал в архивах и в сети ответы, но на самом деле не нашел их, просто бит и куски. Кажется, есть много предложенных сообщений, но никто из них не имеет ответа.
У меня есть сложная директива, которая использует область действия: true. На самом деле это последняя версия версии 2.x ng-grid, которую я пытаюсь написать для кода очистки, поскольку это просто утечка памяти, как сумасшедшая, и наше приложение «застряло» с ней на данный момент. Вот the plunk that demos the problem. Когда вы щелкаете по сетке и проверяете моментальные снимки кучи, вы увидите несколько «непривязанных» объектов ngGrid. Они только удерживаются слушателями в области действия директивы.
Когда я меняю состояния (используя последнюю версию ui.route), перейдя по нескольким сеткам (состояниям), область действия сетки получает событие $ destroy. Обработчик работает. Однако сама область не получает $ destroy(). Я вижу в снимке кучи, что область действия директивы все еще удерживает элементы через $$ слушателей. Кроме того, scope. $$ destroy не установлен.
Однако объем. прототипIS уничтожен. И потому, что это, я не могу даже назвать $ объема $ уничтожить от $ экранных $ уничтожить обработчика директивы, так как Проты $ уничтожить() вызов изменил определение $ уничтожить до Ноопа:.
ngGridDirectives.directive('ngGrid', ['$compile', '$filter', '$templateCache', '$sortService', '$domUtilityService', '$utilityService', '$timeout', '$parse', '$http', '$q',
function($compile, $filter, $templateCache, sortService, domUtilityService, $utils, $timeout, $parse, $http, $q) {
var ngGridDirective = {
scope: true,
compile: function() {
return {
pre: function($scope, iElement, iAttrs) {
$(iElement).on('$destroy', function cleanupElementNgGrid() {
$timeout(function() {
$scope.$destroy();
$scope.destroyedByForce = true;
console.log("I destroyed it.");
},4000);
});
...
Настройка области. $$ listeners = {} с $ timeout 2000 (чтобы дать время для того, чтобы директива закончила очистку моего прослушивателя on-$-destroy, кажется, работает, но он чувствует себя неловко с помощью внутренних функций, а иногда это . не достаточно долго для браузера, чтобы закончить очистку это просто обходным/ляп
Я также попытался это:.
Так что мешает моей директивы области действия п rom, получая $ destroy(), автоматически вызвал его?
Сначала я подумал, что это потому, что мы используем scope: true в параметрах директивы, поскольку прото сфера, похоже, была уничтожена. Поэтому я написал a plunk to try that theory out. Но с этим плунгом область действия директивы должным образом уничтожается, и никакие объекты не просачиваются. На самом деле очень удивительно. Но я не использую одно и то же представление, которое у меня есть в первом plunk; однако я сомневаюсь, что все. Область управления по-прежнему стирается при изменении представлений. У меня все еще есть наблюдатель на внутреннем объекте. Поэтому я бы подумал, что увижу подобную динамику. Но похоже, что $ destroy действительно призван к этой внутренней области.
Любые идеи о том, что помешало бы тому, чтобы объект директивы получал $ destroy()? Кажется, что это связано с масштабом: истинный бит, но я не могу достаточно затмить угловые внутренности, чтобы сказать, почему.
Спасибо заранее,
Джесси
Обновления: Хорошо, я выложу обновление к этому вопросу.
В меру моих возможностей, похоже, что происходит то, что основная область действия элемента (а не область полуизоляции для директивы grid) получает $ destroy() d. Тем не менее, дочерняя область, которая использует эту область действия в качестве прототипа, скорее всего, выйдет из метода $ destroy раньше, потому что self. $$ destroy является истинным (прототипное наследование). Поэтому слушателей и наблюдателей не очищают.
Возможно, я мог бы обновить директиву, чтобы полностью изолировать ее по охвату, но у меня нет времени, чтобы разобраться с последствиями этого.
Я также нашел, что это больше, чем просто $ destroy. Сама область $ имеет множество функций, определенных на ней директивой, которая формирует замыкание вокруг внутренних варов, которые содержат много памяти.
Итак, я написал службу, которая предоставляет дополнительную очистку, которая легко вводится в сомнительную директиву сетки. У меня есть демонстрация плунжера, но я не могу опубликовать его в главной части из-за моей низкой репутации :). Теперь вы можете переключать сетки на все, что вам нравится, и нет, но текущие сетки останутся в куче.
Надеется, что это помогает кто-то идти вперед,
J
Вот ссылка на другой планшет, на котором показано упомянутое выше разрешение. http://plnkr.co/edit/r2uTKTJW2yJTbHx0kXYB – jessewolfe
Привет, У меня была проблема, которая, как мне кажется, связана, вы нашли причину, почему $ destroy не вызывается в области? http://stackoverflow.com/questions/27467210/angular-directive-memory-leaks – Barnash
Может быть интересно: в этой статье рассказывается о перерывах, которые могут произойти в цепочке $ destroy из-за плохих халдингов суб-областей (а именно: с помощью jquery) http: //www.bennadel.com/blog/2706-always-trigger-the-destroy-event-before-removing-elements-in-angularjs-directives.htm – Offirmo