angularjs - Angular 广播无法与独立服务一起使用

标签 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');
    });

  }]);

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

如何通过定义我所拥有的依赖关系来实现这种通信?我无法将 testService 定义为 PhaseListener 的依赖项。 testService 是一个模块示例,可以单独编码并使其可以轻松地与我的应用程序集成。

依赖关系: 服务 1 => 共享服务 <= 服务 2

消息传递: 服务 1 => 共享服务 => 服务 2

最佳答案

服务是单例的,因此虽然确实必须加载它们才能工作,但一旦它们加载,实例化它们就不需要太多成本。你最终不会得到 12 份副本。我每天都使用这种模式,我发现最好让所有服务都依赖于 app.js。在我的主“运行”处理程序中,我注入(inject)了我计划使用的所有主要服务。这保证了它们可用,并且在其他人开始执行任何可能发出事件的操作之前加载它们。加载它们不需要太多 RAM,并且在事件实际触发之前没有工作负载。没有什么理由不这样做 - 服务被设计为全局实体,并且延迟加载它们没有太大值(value)。

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');
        };
    }]);

如果需要,您仍然可以在服务中定义作用域局部变量 - 但它是可选的。

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

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

关于angularjs - Angular 广播无法与独立服务一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25610889/

相关文章:

带有通知 channel 的 Android 8 前台服务

javascript - 将基于鼠标移动设置 div 样式的函数从 jQuery 转换为 Angular 会使坐标变得困惑

javascript - Angular.js : on form submit action is not calling

JavaFX - 如何将事件句柄分配给标签数组?

events - Firefox 扩展可在页面关闭后注销用户

javascript - 为 jasmine 集成测试发出真正的异步请求

service - AdMob : How to query admob for my app earnings

javascript - 应用 ng-model 过滤器时,ng-repeat 负载为空

javascript - Angular 引导 ui 模态

javascript - 如何在 QWebView 中通过 C++ 触发 JavaScript 事件