如何使用angularjs-nvd3-directives避免内存泄漏

时间:2014-07-18 09:14:14

标签: angularjs d3.js memory-leaks nvd3.js

我正在使用angularjs-nvd3-directives来创建一个angularjs应用程序来渲染图表。

使用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 = {};
    }
  });
});

当我从我的应用程序中删除图表时,内存使用量总是回到初始值。

使用图表: with graph 内部消除: without

有没有其他方法可以释放这些图表生成的内存?

jsfiddle来证明这个问题。

3 个答案:

答案 0 :(得分:2)

您可能忘记删除窗口调整大小侦听器。

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元素,但它似乎不是最好的方法。

答案 1 :(得分: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内存泄漏问题。但是数据端(数组)仍有一些内存泄漏。

答案 2 :(得分:0)

我建议您图表移动到自己的指令,该指令将在其模板上保存nvd3指令并监听每个指令的范围。
<登记/> $destroy也会破坏此事件的元素。

控制器应检索数据并将其分配给指令。

您可能希望收听指令上的$routeChangeStart,因此清理将封装在使用数据的部分上。这样您就可以避免重复的代码。

我使用这种技术来清理我使用模态的指令,所以我没有重复的事件监听器或ids。