Angular утечки памяти директивы?
Я использую этот простой html файл для воспроизведения утечки памяти, которую я нашел:
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.min.js"></script>
<script>
var app = angular.module('testApp', []);
app.directive('directive1', function() {
return {
template: '<div directive2></div>',
scope: true
};
});
app.directive('directive2', function () {
function LeakObject() {}
function Foo() {
this.bar = function($scope) {
$scope.nottheredude;
};
}
return {
scope: true,
link: function($scope) {
$scope.memoryThatLeaks = new LeakObject();
new Foo().bar({});
new Foo().bar($scope);
}
};
});
</script>
</head>
<body ng-app="testApp">
<button ng-click="show = !show">Toggle</button>
<div ng-if="show">The directive <div directive1></div></div>
<div ng-if="!show">Nothing</div>
</body>
</html>
У меня есть директива, которая создает только новую область и имеет другую директиву в своем шаблоне.
Другая директива делает что-то немного странное (я пытался сузить проблему до того, что вызывает утечку, и что самый короткий код, который я нашел, что воспроизводит проблему).
В моем основном html я просто переключаюсь между ничего и directive1
с помощью простого ng-if
.
Обратите внимание, что directive2
также создает новый объект в $scope
, называемом LeakObject
. Я ожидаю, что этот объект будет собран из мусора, когда я перейду к div без ничего, так как область действия директивы должна умереть и все данные на ней с ней, но в соответствии с инструментом моментального снимка Chrome heap в режиме инкогнито, он не получает нераспределенные.
Я пытаюсь понять, почему это происходит, и почему, если я прокомментирую инструкцию в методе bar
, этого не произойдет.
Шаги для воспроизведения:
- Откройте этот файл в инкогнито
- Откройте инструменты разработчика и перейдите в раздел Профили
- Обновить страницу
- Дважды нажмите
Toggle
(теперь вы снова видите Nothing
на экране)
- Сделайте снимок кучи
- Напишите "утечку" в фильтре, чтобы вы могли видеть, что
LeakObject
все еще существует, когда он не должен действительно существовать.
Вот как это должно выглядеть:
![The problem]()
Кто-нибудь может помочь/объяснить?
Ответы
Ответ 1
Все работает так, как ожидалось,
после выполнения ваших шагов я не вижу никаких объектов утечки в снимке.
вы можете добавить следующий код в функцию ссылки, чтобы увидеть, что директива фактически уничтожает
Контроллер и директивы излучают событие непосредственно перед их уничтожением. Здесь вам предоставляется возможность снести ваши плагины и слушателей и в значительной степени выполнять сборку мусора.
Подпишитесь на $scope. $On ('$ destroy',...) event
$scope.$on('$destroy',function(){
//$scope.memoryThatLeaks = null;
alert('!');
});