Angularjs pubsub vs $broadcast
Posted
技术标签:
【中文标题】Angularjs pubsub vs $broadcast【英文标题】: 【发布时间】:2014-03-05 12:04:39 【问题描述】:我一直在阅读 Angularjs 中的事件传递,但我不相信使用 $broadcast 是个好主意。
one 之类的博客提倡习惯使用 $on,即使它“感觉有点矫枉过正”。
我的困惑是,该实现使用深度优先遍历范围并寻找订阅者,这使得事件的速度取决于您的树结构。 以下是 Angular 中的一些代码:
// Insanity Warning: scope depth-first traversal
// yes, this code is a bit crazy, but it works and we have tests to prove it!
// this piece should be kept in sync with the traversal in $digest
if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling))))
while(current !== target && !(next = current.$$nextSibling))
current = current.$parent;
此外,您似乎可以使用这些方法破解依赖注入。
替代方案只是一个缓存事件类型和回调的服务,并直接调用它们。这需要您清理订阅以避免泄漏。
我的问题是,关于 $broadcast/$on 范式的动机有什么我遗漏的吗?或者与更传统的 pubsub 相比,使用它有什么好处?
如果我的问题不够清楚,请告诉我,感谢您抽出宝贵时间。
【问题讨论】:
这是一个很好的问题,谢谢你的提问。 【参考方案1】:我认为你没有遗漏任何东西。您已成功概述了每种方法的优缺点。
$broadcast
/$on
方法不需要您取消订阅,但它的效率并不高,因为它会广播到所有范围。它的进入门槛也很低。您不需要注入任何服务,也不需要创建它们。他们向所有人广播,所以这是一种更简单的方法。
发布/订阅方式更为直接。只有订阅者才能获得事件,因此它不会进入系统中的每个范围以使其工作。然而,它更复杂,因为您需要使用回调处理程序编写服务,并且您必须记住取消订阅。在我看来,记住退订是相当大的。如果你不正确,你会得到内存泄漏。而且你不会知道它,直到它在 3 个月内出现问题。
我明白为什么内置方法是$broadcast
。
【讨论】:
不知道有没有办法自动退订。如果发布/订阅模型与 Angular 集成,您可以在$destroy
上自动取消订阅。控制器和指令通常对应一个范围,并且可以以漂亮的1::1
方式取消订阅它的销毁。服务/工厂/提供者的自动化不太明显,但通常它们无论如何都是单例的。
你可以做类似的事情,但是你会将范围传递给服务。这似乎不是最佳做法。
就我个人而言,将$rootScope
传递到服务中并没有什么大问题。我理解内心的反应,但我内心的实用主义者会说“为什么不呢?”。
传递$rootScope
是不够的。这允许您在 $rootScope 被销毁时销毁所有 pub subs,但您需要传入单独的 $scope
对象。不这样做的原因是服务应该与层次结构无关。在这种情况下,这样做仍然很安全,但我喜欢它作为一个坚定的规则。
$broadcast
不一定向所有人“广播”。它仅将事件发送到 Scope 的子作用域。 $rootScope.$broadcast
将发送给“每个人”,但控制器的 $scope.$broadcast
只会发送给包含在该控制器中的控制器和指令范围。【参考方案2】:
我正在研究同样的问题。特别是如何允许服务在不访问 $rootScope 的情况下广播和订阅事件(由于某些原因很糟糕)。 我从这里使用了非常出色的 js-signals 实现: http://millermedeiros.github.io/js-signals/ 并将其包装成一个角度服务。
github 要点在这里:https://gist.github.com/anonymous/b552c7fafa77427e6d06
【讨论】:
以上是关于Angularjs pubsub vs $broadcast的主要内容,如果未能解决你的问题,请参考以下文章
AngularJS 笔记之创建服务方式比较 : factory vs service vs provider 。
AngularJS2学习笔记 ——环境搭建(win7vs2012)