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

如何使用angularjs-nvd3指令避免内存泄漏,angularjs,d3.js,memory-leaks,nvd3.js,Angularjs,D3.js,Memory Leaks,Nvd3.js,我正在开发一个angularjs应用程序,使用angularjs-nvd3-Directions来渲染图表 在使用Chrome开发者工具进行检查后,我检测到一些与图表相关的内存泄漏。当用户浏览包含图表的不同视图时,内存永远不会完全释放 我已经在对图形控制器进行一些清理: $scope.$on('$destroy', function() { d3.select( '#exampleId' ).remove(); d3.select( '#exampleId2' ).remove();

我正在开发一个angularjs应用程序,使用angularjs-nvd3-Directions来渲染图表

在使用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 = {};
    }
  });
});
当我从我的应用程序中删除图表时,内存使用量总是回到初始值

如图所示: 但不包括:

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


演示此问题。

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

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

我建议您将图形移动到自己的指令中,该指令将nvd3指令保存在模板上,并侦听每个指令的作用域。

$destroy
同时销毁此事件中的元素。

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

您可能需要听指令中的
$routeChangeStart
,因此清洗将封装在使用数据的部件上。这样可以避免重复代码。


我使用这种技术来清理使用modals的指令,这样我就不会有重复的事件侦听器或id

github也存在类似的问题:

正如我在那里解释的,以下方法效果更好:

  $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
angular.element(document.body.querySelectorAll('.nvd3')).remove();

这解决了SVG内存泄漏问题。但是数据端(阵列)仍然存在一些内存泄漏。

我没有答案,但我也迫切希望找到一种方法,在状态/路由更改时销毁图表。这个问题在这里讨论:嗨!您使用哪个版本的nvd3?@Artemis v1.1.15-beta
window.onresize=null
是一个很好的观点,它在JSFIDLE示例中运行良好。然而,对于更复杂的图形,似乎仍然存在与nvd3图形相关的内存泄漏。如果我没有其他答案,我想你会得到奖励。你也可以尝试直接使用D3API——有时你可以获得一些性能提升。Nvd3只是D3API的包装器。你可以看这里-。我现在使用我自己的指令,没有nvd3,只有D3。这样我就可以准确地知道要在范围内销毁什么。$destroy。我像这样解决了95%的泄漏。感谢您的输入,我不再使用nvd3,但这非常有趣。它看起来像是d3.selectAll('svg').remove()但以角度的方式。不。我已经有了d3.selectAll('svg').remove();这是行不通的。顺便说一句,我在广播调用中结合了这两个代码(你写的和我写的)。为了通知d3用户,我使用了
d3.select(“#”+attrs.id)。remove()$destroy
事件的我的自定义指令中。这对我有用。仍然有泄漏,但比以前少了。