角度广播不与独立服务合作

时间:2014-09-01 17:54:11

标签: angularjs events service scope broadcast

我目前正在尝试使用$ rootScope。$ broadcast方法来触发我的angularjs服务中的事件。为此,我创建了一个负责触发事件的服务,并设置了一个不同的服务来拾取事件。重要的是,接收事件的服务应独立于应用程序的其余部分,这就是我采用共享服务方法的原因。

我的广播服务(共享),在我的应用中调用以触发事件:

angular.module('myModule')
  .factory('phaseListener', ['$log', '$rootScope',  function ($log, $rootScope) {

    var phaseListener= {};

    phaseListener.broadcastPhase = function(phase) {
      $rootScope.$broadcast('test');
    };

    return phaseListener;
}]);

在以下服务' testService'我正在听这个事件,但它没有被触发。我从另一个服务调用broadcastPhase()方法,并触发该方法。

angular.module('myModule')
  .factory('testService', [ '$rootScope', '$scope', '$log', 'phaseListener', 
    function ($rootScope, $scope, $log, phaseListener) {   

    $rootScope.$on('test', function() {
      $log.debug('This works');
    });

  }]);

如果我在当前加载的控制器中监听事件,它就能正常工作。但我的目标是触发当前未加载的其他控制器/服务中的事件(至少在页面上尚未显示)。通过将phaseListener定义为testService的依赖项,我希望它能够在后台加载。

如何通过定义依赖关系来实现此通信?我无法将testService定义为phaseListener的依赖项。 testService是一个模块的示例,可以单独编码,并允许它轻松地与我的应用程序集成。

依赖关系: 服务1 => SharedService< = Service 2

信息: 服务1 => SharedService =>服务2

2 个答案:

答案 0 :(得分:1)

服务是单身,所以虽然它们必须被加载才能使它们工作,但一旦它们存在,实例化它们的成本就不高。它不像你最终会得到12份副本。我每天都使用这种模式,并且我发现只做app.js的所有服务依赖项是最好的。在我的主要'运行'处理程序我注入了我计划使用的所有主要服务。这保证了它们可用,并且在任何其他人开始做任何可能发出事件的事情之前它们被加载。加载它们并不需要太多RAM,并且在事件实际被触发之前没有工作量。没有理由不这样做 - 服务被认为是全球实体,延迟加载它们并没有多大价值。

angular.module('myApp', ['myService1', 'myService2', 'myService3'])
.run(['$rootScope', 'myService1', 'myService2', 'myService3', function() {
    // NOTE: You may or may not actually need to do anything here. But by asking the
    // injector for each service you can guarantee that they're loaded when the app
    // starts. That lets them set up any listeners necessary for them to function.
    // Note that the order in which you ask for them here will determine the order in
    // which they're instantiated!
});

您也可以考虑使用' service'而不是工厂'。你没有利用两者之间的差异,所以工厂没有给你任何好处。服务基本上只是工厂的速记,而你通常会想要这样的方式......"机制,如果你使用服务,你将保存两行代码(var定义和return语句):

angular.module('myModule')
    .service('phaseListener', ['$log', '$rootScope',  function ($log, $rootScope) {
        this.broadcastPhase = function(phase) {
            $rootScope.$broadcast('test');
        };
    }]);

如果您愿意,您仍然可以在服务中定义范围 - 本地 - 但它是可选的。

我唯一不会这样做的是,如果有很多这样的话......但在这种情况下,我会质疑应用程序的架构。我正在构建一个极其复杂的应用程序,具有6个月的开发周期,到目前为止我们只有9项服务。这只是轶事,但我仍然会惊讶地看到有人为一个拥有30多个应用程序的应用程序提供了良好的案例。通常在那时你想重新考虑一下“经理”的经历。模式实际上是为您做的,这是工厂和提供商实际上有用的地方。在那里,您可以拥有处理所有发布/订阅工作的核心服务,并在其中管理根据应用程序状态执行各种特定功能的智能对象。

这样的一个很好的例子是模态窗口管理器。您可能有几种类型的模态都具有不同的行为。您可以制作一个能够根据参数生成每种类型的主服务,而不是制作三种服务。然后你可以区分灯箱和"纯"模态,但仍然通过单一服务管理它们。

答案 1 :(得分:1)

我找到了一种巧妙的方法来实现我的目标。也许有人可以使用它:因为我不知道在启动时必须听取广播事件的所有服务,所以我不能像通常在角度中那样添加依赖项。相反,我可以通过“$ injector.get('serviceName');”在运行时手动注入服务。在此之后,服务被注入,任何后续广播也将到达新注入的服务。