Как избежать утечек памяти с помощью angularjs-nvd3-директив
Я работаю над приложением angularjs, используя директивы angularjs-nvd3 для рендеринга диаграмм.
После проверки с помощью инструментов разработчика Chrome я обнаружил некоторые утечки памяти, связанные с диаграммами. Когда пользователь перемещается по различным представлениям, содержащим диаграммы, память никогда полностью не освобождается.
Я уже делаю очистку на графических контроллерах:
$scope.$on('$destroy', function() {
d3.select( '#exampleId' ).remove();
d3.select( '#exampleId2' ).remove();
...
});
И в событии routeChange:
myApp.run(function($rootScope, $templateCache) {
//try to clear unused objects to avoid huge memory usage
$rootScope.$on('$routeChangeStart', function(event, next, current) {
if (typeof(current) !== 'undefined'){
//destroy all d3 svg graph
d3.selectAll('svg').remove();
nv.charts = {};
nv.graphs = [];
nv.logs = {};
}
});
});
Когда я удаляю диаграммы из своего приложения, использование памяти всегда возвращается к исходному значению.
С графиком:
Whithout:
![without]()
Есть ли другой способ освобождения памяти, сгенерированной этими диаграммами?
jsfiddle, чтобы продемонстрировать эту проблему.
Ответы
Ответ 1
Вы можете забыть удалить прослушиватели с изменением размера окна.
angularApp.run(function($rootScope) {
$rootScope.$on('$routeChangeStart', function(event, next, current) {
if (typeof(current) !== 'undefined'){
//destroy d3 stuff
window.nv.charts = {};
window.nv.graphs = [];
window.nv.logs = {};
// and remove listeers for onresize.
window.onresize = null;
}
});
});
Также вы можете попробовать удалить весь элемент svg, но это не похоже на лучший способ.
Ответ 2
В github аналогичная проблема: https://github.com/cmaurer/angularjs-nvd3-directives/issues/193
Как я объяснил там, работала лучше:
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
angular.element(document.body.querySelectorAll('.nvd3')).remove();
Это устраняет утечки памяти SVG. Но все же есть некоторые утечки памяти на стороне данных (Array).
Ответ 3
Я рекомендую вам переместить ваш график в свои собственные директивы, которые будут содержать директивы nvd3 на своих шаблонах и слушать каждую директиву для области.
> $destroy
также уничтожает элемент на этом событии.
Контроллеры должны извлекать данные и назначать их директиве.
Возможно, вам захочется прослушать $routeChangeStart
в директиве, поэтому очистка будет инкапсулирована на ту часть, которая использует данные. Таким образом, вы избежите дублирования кода.
Я использую эти методы для очистки моих директив, использующих модальные файлы, поэтому у меня нет дубликатов событий или идентификаторов событий.