Некоторое время искал в архивах и в сети ответы, но на самом деле не нашел их, просто бит и куски. Кажется, там много предложенных сообщений, но никто из них не имеет ответа.
У меня есть сложная директива, которая использует scope: true. Это на самом деле версия последней версии ng-grid последней версии 2.x, которую я пытаюсь написать для кода очистки, поскольку это просто утечка памяти, как сумасшедшая, и наше приложение "застряло" с ней на данный момент. Здесь панель, которая демонстрирует проблему. Когда вы щелкаете по сетке и проверяете моментальные снимки кучи, вы увидите несколько "непривязанных" объектов ngGrid. Они только удерживаются слушателями в области действия директивы.
Когда я меняю состояния (используя последнюю версию ui.route), перейдя по нескольким сеткам (состояниям), область директивы grid IS получает событие $destroy. Обработчик работает. Однако сама область не получает $destroy(). Я вижу в снимке кучи, что область действия по-прежнему удерживается на элементах через $$ прослушиватели. Кроме того, scope. $$ destroy не установлен.
Однако scope.prototype IS уничтожен. И поскольку это так, я даже не могу назвать $scope. $Destroy из обработчика директивы $on-$ destroy, поскольку вызов proto $destroy() изменил определение $destroy to noop:
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, кажется, работает, но он чувствует себя неловко с помощью внутренних функций, и иногда это не достаточно долго, чтобы браузер завершил очистку. Это просто работа /kludge.
Я также пробовал это:
Итак, что мешает моей области директивы получать $destroy() автоматически вызываемый на ней?
Сначала я думал, что это связано с тем, что мы используем scope: true в параметрах директивы, так как прото сфера, похоже, была уничтожена. Поэтому я написал планку, чтобы попробовать эту теорию. Но с этим плунгом область действия директивы должным образом уничтожается, и никакие объекты не просачиваются. На самом деле очень удивительно. Но я не использую одно и то же представление, которое у меня есть в первом plunk; однако я сомневаюсь в этом. Область управления по-прежнему стирается при изменении представлений. У меня все еще есть наблюдатель на внутреннем объекте. Поэтому я бы подумал, что увижу подобную динамику. Но похоже, что $destroy действительно вызывается в этой внутренней области.
Любые идеи о том, что помешало бы тому, чтобы область действия директивы получала вызов $destroy()? Кажется, что это связано с областью действия: истинный бит, но я не могу достаточно замаскировать внутренние элементы Angular, чтобы сказать, почему.
Заранее спасибо,
Джесси
Обновление: ОК, я опубликую обновление для этой проблемы.
В меру моих возможностей кажется, что происходит то, что основная область для элемента (а не полуизолированная область для директивы grid) получает $destroy() d. Тем не менее, дочерняя область, которая использует эту область действия в качестве прототипа, скорее всего, выйдет из метода $destroy раньше, потому что self. $$ destroy является истинным (прототипное наследование). Поэтому слушатели и наблюдатели не очищаются.
Я, вероятно, мог бы обновить директиву, чтобы полностью изолировать ее по охвату, но у меня нет времени, чтобы разобраться с последствиями этого.
Я также нашел это больше, чем просто $destroy. Сама область $имеет множество функций, определенных на ней директивой, которая формирует замыкание вокруг внутренних варов, которые содержат много памяти.
Итак, я написал службу, которая предоставляет дополнительную очистку, которая легко вводится в сомнительную директиву grid. У меня есть демонстрация плунжера, но я не могу опубликовать его в главной части из-за моей низкой репутации:). Теперь вы можете переключать сетки на все, что вам нравится, и нет, но текущие сетки останутся в куче.
Надеюсь, это поможет кому-то идти вперед,
J