当前位置: 首页 > 面试题库 >

销毁示波器时是否应删除有角的$ watch?

万俟心思
2023-03-14
问题内容

当前正在从事一个项目,在该项目中,当我们不从被破坏的示波器中清除广播订阅时,会发现大量内存泄漏。以下代码已解决此问题:

var onFooEventBroadcast = $rootScope.$on('fooEvent', doSomething);

scope.$on('$destroy', function() {
    //remove the broadcast subscription when scope is destroyed
    onFooEventBroadcast();
});

这种做法也应该用于手表吗? 下面的代码示例:

var onFooChanged = scope.$watch('foo', doSomething);

scope.$on('$destroy', function() {
    //stop watching when scope is destroyed
    onFooChanged();
});

问题答案:

不,您不需要删除$$watchers,因为一旦销毁范围,它们将被有效删除。

从角的源代码(v1.2.21),Scope$destroy方法:

$destroy: function() {
    ...
    if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
    if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
    if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
    if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
    ...
    this.$$watchers = this.$$asyncQueue = this.$$postDigestQueue = [];
    ...

因此,将$$watchers清空该数组(并且将范围从范围层次结构中删除)。

watcher无论如何,从阵列中删除都是注销功能所要做的:

$watch: function(watchExp, listener, objectEquality) {
    ...
    return function deregisterWatch() {
        arrayRemove(array, watcher);
        lastDirtyWatch = null;
    };
}

因此,取消$$watchers“手动” 注册没有意义。

不过,您仍然应该注销事件监听器(正如您在帖子中正确提到的那样)!

注意: 您只需要取消注册在其他作用域上注册的侦听器。无需注销正在被破坏的作用域上注册的侦听器。
例如:

// You MUST unregister these
$rootScope.$on(...);
$scope.$parent.$on(...);

// You DON'T HAVE to unregister this
$scope.$on(...)

(感谢@约翰为它指向了

另外,请确保您取消注册所有超出被破坏范围的元素的事件侦听器。例如,如果您有一条指令在父节点或上注册侦听器<body>,那么您也必须注销它们。
同样,您不必删除注册在要破坏的元素上的侦听器。

有点与原始问题无关,但是现在在$destroyed要销毁的元素上也分配了一个事件,因此您也可以将其挂接到(如果适合您的用例):

link: function postLink(scope, elem) {
  doStuff();
  elem.on('$destroy', cleanUp);
}


 类似资料:
  • 问题内容: 我一直试图在Python中找到RAII。资源分配即初始化是C ++中的一种模式,通过该模式可以在创建对象时对其进行初始化。如果失败,则抛出异常。这样,程序员便知道该对象永远不会处于半构建状态。Python可以做到这一点。 但是RAII还可以使用C ++的作用域规则来确保对象的及时销毁。一旦变量从堆栈弹出,它就会被销毁。这可能在Python中发生,但前提是没有外部或循环引用。 更重要的是

  • 两者的区别是什么 和 例如: 我用这个或那个真的重要吗?

  • C++20引入了“destroying”(带有标记类型),是的新重载。 这到底是什么,什么时候有用?

  • 我正在构建一个基于railsguide的rails应用程序 它在erb中调用的语法是... 控制器定义 与在application.html.erb中使用“application”相关联的错误

  • 问题内容: Java中的InputStreams和OutputStreams是否在销毁时关闭()?我完全理解这可能是错误的形式(尤其是在C和C ++世界中),但是我很好奇。 另外,假设我有以下代码: 无名的FileInputStream是否在p.load()之后超出范围,并因此被破坏,就像C ++范围规则一样?我尝试在Google上搜索Java的匿名变量范围,但这并没有达到我的预期。 谢谢。 问题

  • 问题内容: 自从我使用Java以来​​已经有5年了,那时,每当您想分配需要清理的对象(例如套接字,DB句柄)时,都必须记住添加一个块并在其中调用cleanup方法。那里。 相比之下,在C++(或确定对象生存期的其他语言,例如Perl)中,类实现程序将定义一个析构函数,该函数在该类的对象超出范围时执行清除。这种方法的优点是对象的用户不会忘记清理它- 即使抛出异常,析构函数也会被自动调用。这种方法用R