AngularJS:如何正确使用指令、范围和绑定(bind)以避免内存泄漏?

标签 angularjs data-binding angularjs-directive angularjs-scope

我正在尝试为 AngularJS 应用程序内存泄漏找到解决方案。因为我是 AngularJS 世界的新手,所以我真的不知道从哪里开始以及从哪里纠正和优化我的代码。

我试图先给你一些应用程序的描述。之后我会发布一些我可以测量的内存统计数据。我使用了三个诊断工具来测量使用的内存:Windows (7) Task Manager、Firefox about:memory 和 Firefox Extension MemChaser。

应用

  • 应用程序嵌入在页面中,应加载一次并在其中停留至少 24 小时
  • 通过 $http() Ajax 请求
  • 以 1 到 60 分钟的间隔连续加载数据
  • 数据是具有一些层次结构的 JSON 对象
  • 对于此层次结构的每一层,都有一个自定义组件(具有隔离范围)
  • 数据的选定部分将被注意到并保留在 Ajax 请求之外
  • 大多数指令加载一个 html 文件(通过 $http())以将其编译为模板

  • 统计数据
  • Windows 任务管理器

    The memory used by Firefox increases by 50 - 100 MB per hour.

  • 关于:内存
                                       Size (MB)   20 min diff  Size (MB)
    JS-Main-Runtime                     32         36/+113%      68
    JS-Main-Runtime-GC-Heap-Committed   20         27/+135%      47
    Heap-Allocated                      54         29/+54%       83
    Heap-Committed                      63         28/+44%       91
    JS-GC-Heap                          31         26/+84%       57
    Private                            156         58/+37%      214
    Resident                           175         62/+35%      237
    VSize                              509         86/+17%      595
    
  • MemChaser 0.5.2.1
                   12:17   12:27   12:57   13:17
    Resident (MB)  140     164     243     270     
    iGC (ms)        42      24      40      42
    CC (ms)          3      53     206     286
    

    Resident: Memory used by the process that is present in the physical memory. iGC: Duration of the last garbage collector activity. CC: Duration of the last cycle collector activity.


  • 这些结果非常引人注目,似乎循环收集器给出了最好的提示。如果我在没有 View 的情况下运行我的应用程序(只是 Ajax 请求),则不会发生任何戏剧性的事情。如果我禁用动态模板加载,则与具有动态模板的版本没有明显区别。因此,这两个主题似乎不是原因。

    我的想法:每个 Ajax 请求都会创建新的范围和 DOM 节点。之后可能会删除 DOM 节点,但带有数据的范围可能仍会保留在内存中。这是我的内存泄漏的可能情况和原因吗?

    那么我应该如何正确使用 AngularJS 指令、范围和绑定(bind)来避免像这样的内存泄漏呢?

    我会非常高兴任何帮助。

    托拜厄斯

    最佳答案

    我使用 AngularJS Batarang Chrome 扩展程序可帮助调试这些类型的问题。监视此扩展程序的模型和性能选项卡,以了解任何悬空或泄漏的范围。确保当您不再需要特定范围时,您的 $destroy它。例如。看看ngRepeat does this .

    从文档中:

    $destroy()

    Removes the current scope (and all of its children) from the parent scope. Removal implies that calls to $digest() will no longer propagate to the current scope and its children. Removal also implies that the current scope is eligible for garbage collection.

    The $destroy() is usually used by directives such as ngRepeat for managing the unrolling of the loop. Just before a scope is destroyed, a $destroy event is broadcasted on this scope.
    Application code can register a $destroy event handler that will give it a chance to perform any necessary cleanup. Note that, in AngularJS, there is also a $destroy jQuery event, which can be used to clean up DOM bindings before an element is removed from the DOM.





    $destroy() must be called on a scope when it is desired for the scope and its child scopes to be permanently detached from the parent and thus stop participating in model change detection and listener notification by invoking.

    关于AngularJS:如何正确使用指令、范围和绑定(bind)以避免内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19682593/

    相关文章:

    c# - 如何防止绑定(bind)触发 TextChanged 事件?

    javascript - 带有指令和翻译的 Angular SweetAlert

    wpf - 绑定(bind)文本 block 样式/转换器

    angularjs - 在 AngularJS 中将指令插入 HTML 中?

    javascript - 使用 $watch 更新数据,ng-repeat 不反射(reflect)变化

    AngularJS 类型错误 : Cannot read property 'insertBefore' of null

    angularjs - Angular 4 和 Angular JS 1x 的共存

    javascript - 如何从 html 更改 angularjs 变量

    html - Angular Json 循环

    javascript - 为什么数据绑定(bind)不起作用? (使用嵌套的 foreach 循环)