2014-09-01 170 views
2

我目前正在尝试使用$ rootScope。$广播方法来触发我的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 < =服务2

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

+0

由于这些控制器/服务未加载,因此'$ on'侦听器也未加载。所以这将永远不会工作。你必须确保服务或控制器功能已经运行,你希望他们'听'这些事件。 – RoryKoehein 2014-09-01 18:06:30

+0

如果我无法在我的phaseListener服务中添加依赖项,我该如何做到最好? – jimmy 2014-09-01 19:00:22

+0

就个人而言,我会使用UI路由器来改变应用程序的'状态',一旦某个事件被触发。状态可以与控制器/服务/模板结合使用。 https://github.com/angular-ui/ui-router – RoryKoehein 2014-09-01 19:03:54

回答

1

我发现了一个很好的方式来实现我所期待的。也许有人可以使用它:因为我不知道在启动时需要监听广播事件的所有服务,所以我不能像通常那样添加依赖项。相反,我可以通过“$ injector.get('serviceName');”在运行时手动注入服务。在此之后,服务被注入并且任何后续广播也将到达新注入的服务。

1

服务是单身,因此,尽管这是真的,他们必须要加载为他们工作,一旦他们在那里没有太多的成本让他们实例化。这不像你最终会有12份。我每天都会使用这种模式,并且我发现最好只制作app.js的所有服务依赖项。在我的主要“运行”处理程序中,我注入了所有计划使用的主要服务。这保证了它们可用,并且在其他人开始做任何可能发出事件的事情之前加载它们。加载它们并不需要太多内存,并且在事件实际被触发之前没有任何工作量。几乎没有理由不这样做 - 服务是全局实体,而延迟加载它们并没有多大价值。

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! 
}); 

你也可以考虑使用'服务'而不是'工厂'。你没有利用两者之间的差异,所以工厂不会给你带来任何好处。服务基本上只是工厂“通常需要这种方式...”机制的简写形式,如果您使用服务,则会保存两行代码(var定义和return语句) :

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

如果你愿意,你仍然可以在服务中定义scope-locals - 但它是可选的。

我不会这样做的唯一时间是,如果有很多他们......但在这种情况下,我会质疑该应用程序的体系结构。我正在构建一个具有6个月开发周期的非常复杂的应用程序,到目前为止我们只有9个服务。这只是一个轶事,但我仍然很惊讶地发现有人为其中30多个应用程序提供了一个好的例子。通常在那个时候,你想重新考虑'管理者'模式实际上为你做了什么,这就是工厂和提供者实际上有用的地方。在那里你可以拥有核心服务来处理所有的pub/sub工作,并管理其中的智能对象,这些智能对象根据应用程序的状态执行各种特定的功能。

一个很好的例子就是模态窗口管理器。你可能有几种类型的模态都有不同的行为。您可以创建一个基于参数生成每种类型的主服务,而不是创建三个服务。然后,您可以区分灯箱和“纯”模式,但仍然通过单一服务管理它们。

+0

感谢您的详细解释。这证实了我所害怕的。我想我必须在启动时以某种方式连接服务。我希望能够创建某种模块/插件类型的体系结构,您可以编写自己的服务/控制器并将其插入基本应用程序,而无需更改现有应用程序中的任何内容。看来我将不得不引入一些虚拟服务来处理所有的依赖关系。也感谢工厂/服务提示 - 我肯定会看看这个。 – jimmy 2014-09-02 04:39:39