【问题标题】:How to avoid memory leaks using angularjs-nvd3-directives如何使用 angularjs-nvd3-directives 避免内存泄漏
【发布时间】:2023-03-18 00:30:01
【问题描述】:

我正在开发一个使用 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 = {};
    }
  });
});

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

用图表: 没有:

还有其他方法可以释放这些图表产生的内存吗?

jsfiddle 演示问题。

【问题讨论】:

  • 我没有答案,但我也渴望找到一种方法来破坏状态/路线变化的图表。这个问题在这里讨论:github.com/novus/nvd3/pull/396
  • 嗨!您使用哪个版本的 nvd3?
  • @Artemis v1.1.15-beta

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


【解决方案1】:

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 内存泄漏问题。但是在数据端(数组)还是有一些内存泄漏。

【讨论】:

  • 感谢您的输入,我不再使用 nvd3 了,但这很有趣。它看起来像d3.selectAll('svg').remove();,但有角度。
  • 不。我已经有了 d3.selectAll('svg').remove();这没有用。顺便说一句,我在广播调用中结合了这两个代码(你写的和我的)。
  • 只是为了通知 d3 用户,我在 $destroy 事件的自定义指令中使用了 d3.select( "#"+attrs.id ).remove();。它对我有用。仍然有泄漏,但比以前少了。
【解决方案2】:

我建议您将图表移动到您的自己的指令,这些指令将在其模板上保存 nvd3 指令并监听每个指令的范围。

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

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

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

我使用这种技术来清理使用模态的指令,因此我没有重复的事件侦听器或 id。

【讨论】:

  • 我现在使用我自己的指令,没有 nvd3 只有 D3。这样我就确切地知道要在 scope.$destroy 上销毁什么。我像这样解决了 95% 的泄漏。
【解决方案3】:

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

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

【讨论】:

  • window.onresize = null; 是一个很好的观点,它在 jsfiddle 示例中运行良好。但是,对于更复杂的图表,似乎仍然存在与 nvd3 图表相关的内存泄漏。如果我没有其他答案,我想你会得到奖励。
  • 您也可以尝试直接使用 d3 api - 有时您可以获得一些性能提升。 Nvd3 只是 d3 api 的包装器。你可以看这里 - github.com/d3/d3-plugins
猜你喜欢
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
  • 1970-01-01
  • 2012-10-22
  • 2020-04-23
相关资源
最近更新 更多