AngularJS清理和内存泄漏

时间:2016-02-18 22:21:25

标签: javascript angularjs

https://docs.angularjs.org/guide/directive

  

注册范围和元素的监听器是   当它们被摧毁时自动清理,但如果你   在服务上注册了一个监听器,或者在DOM上注册了一个监听器   没有删除的节点,你必须自己清理它   你冒着引入内存泄漏的风险。

我不明白一件事(实际上我并不了解很多关于Angular的事情,但现在我的目标正是针对这一点)。任何人都可以解释注册的范围和元素“”之间的区别“>在服务上注册了一个监听器,或者注册了一个监听器< strong> on 一个DOM“。这句话中元素和DOM之间的区别是什么。为什么在第一种情况下,监听器会被自动清理,但在第二种情况下它们不会被清除。为什么要注册元素以及 DOM上注册的内容?

1 个答案:

答案 0 :(得分:4)

请注意,我们在这里谈到两种略有不同的清理方式:

  1. 事件监听器功能可能需要清理。
  2. 创建的元素也可能需要清理。
  3. 在这些情况下,Angular会为您清理:

    // Watching scope vars
    $scope.$watch("scopeVariable", function (newVal) { ... });
    $scope.$watch("injectedService.serviceVar", function (newVal) { ... } );
    
    // Listening to events from a scope
    $scope.$on("event", function () { ... });
    
    // Events of the element of a directive,
    // within the directive 'link' function (the docs you referenced)
    element.on('click', function() { ... });
    

    在所有这些情况下,没有必要进行任何清理。 Angular知道某些代码正在侦听事件或观察变量,并且可以取消注册它们。对于元素,因为它将被删除,所有闭包和相关对象将被取消引用,因此后来由垃圾收集器处理。

    另一方面,在以下情况下,Angular不会为您进行清理:

    // Listening to events from rootScope
    $rootScope.$on("event", function () { ... });
    
    // Subscribing to services events
    someInjectedService.subscribeIncomingMessage(function () { ... });
    
    // Adding elements outside directive container element
    var body = $document.find('body').eq(0);
    var newElement = angular.element('<div></div>');
    body.append(newElement);
    
    // Listening to events of elements outside your directive (ie. body)
    body.on("click", function() { ... });
    

    在这些情况下,Angular永远不会破坏您的侦听器,也不会将创建的元素添加到文档的<body>中。

    简单来说,我说Angular会破坏你的范围内 范围内的所有内容,或者你的指令根元素的DOM 中包含的

    ,您有责任听取其他所有内容,或者您​​创建的内容以及放置在指令之外的内容。

    引用角度文档,您可以通过侦听destroy事件进行清理:

      

    最佳实践:指令应该自行清理。您可以   使用element.on('$destroy', ...)scope.$on('$destroy', ...)来运行   删除指令时的清理功能。

    我个人只有在需要清理时才添加这些方法。您需要这样做,特别是如果您为外部事件创建注册元素(即来自websockets或预定超时事件的消息),否则您可能会因为同一事件的多个侦听器而结束(通常会导致错误行为和迟缓)。 / p>