【问题标题】:Not receiving event from $rootScope emitted by my factory没有收到来自我工厂发出的 $rootScope 的事件
【发布时间】:2014-10-02 18:08:28
【问题描述】:

我创建了一个工厂来提供我自己的 Angular $exceptionHandler 实现。 该工厂在 $rootScope 上发出一个事件,向侦听器发出发生错误的信号。 我的侦听器是在监视 $rootScope.$on 事件的指令中定义的。就我的工厂实例拦截异常并发出错误事件而言,一切似乎都很好。但是,据称正在侦听事件的指令从未接收到所述事件。是什么断开导致监听器在指令中错过了这个事件??

澄清:事件完全依赖于 $rootscope 的发射和消费,以避免向下游广播事件。这是设计使然,并且之前已经工作过,或者至少似乎可以在我根据使用相同策略的几个实现编写的 httpLoader 和 httpErrorHandler 中工作。 http://plnkr.co/edit/N0JwYJdxPLur4xYZTUP1?p=info

Plunker:http://plnkr.co/edit/LDbRa0Ew255fOd0EunAq?p=preview

angular.module('demo.services',[]);
angular.module('demo.directives',[]);
angular.module('demo',['demo.services','demo.directives']);

angular.module('demo')
.controller('demoCtrl', function($scope){
  $scope.message="Generate Error";
  $scope.generateError =function(){
    var x;
    x.foo.oops = ':(';
  }
});

angular.module('demo.services')
.factory('$exceptionHandler', function () {
    var $injector = angular.injector(['ng']);
    return function errorCatcherHandler(exception, cause) {
      rootScope = $injector.get('$rootScope');
      rootScope.$emit("httpError",exception);
      console.error(exception);
    };
});


angular.module('demo.directives')
.directive('ngHttpError', ['$rootScope',
  function ($rootScope) {
    return {
      scope: {
        title: '@',
      },
      template: '<div ng-click="showError=false"' +
                'ng-show="showError">'+
                'ERROR! {{errorModel | json}}' + 
                '</div>',
      link: function ($scope) {
        var showError;

        $scope.showError = false;
        $scope.errorModel = {};
        showError = $scope.showError;

        var initScope = function(e,m){
          console.log(m);
          $scope.errorModel = m;
          $scope.showError=true;
        }
        $rootScope.$on("httpError", initScope);
      }
    };
  }
]);

angular.bootstrap(document,['demo']);

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    请记住,$emit() 在作用域层次结构中向上发送事件,$broadcast() 在层次结构中向下发送事件。由于$rootScope 是“根”范围(最顶层/节点),因此在此处使用$broadcast() 将事件“向下”发送到子范围是有意义的。

    $emit(),来自the docs:

    通过范围层次结构向上调度事件名称,通知已注册的 $rootScope.Scope 侦听器。

    $broadcast(),来自the docs:

    向下分发事件名称到所有子作用域(及其子作用域),通知已注册的 $rootScope.Scope 侦听器。

    -- 更新:

    我已更新您的$exceptionHandler 以注入$injector 服务并执行$broadcast() 而不是$emit() - 这似乎可以解决问题:

    angular.module('demo.services')
    .factory('$exceptionHandler', function ($injector) {
        //var $injector = angular.injector(['ng']);
        return function errorCatcherHandler(exception, cause) {
          rootScope = $injector.get('$rootScope');
          rootScope.$broadcast("httpError",exception.message);
          console.error(exception);
        };
    });
    

    顺便说一句,一个相关的问题/答案可以在这里看到:AngularJs/ .provider / how to get the rootScope to make a broadcast?

    【讨论】:

    • 只是我不希望将事件广播到子范围。这包含完全针对 $rootscope 的消息传递策略,这是意图。见:plnkr.co/edit/N0JwYJdxPLur4xYZTUP1?p=preview
    • 顺便说一句:您是否测试过并确认了这是问题所在?
    • 好吧,我已经尝试使用您的 generateError() 函数进行 $broadcasting - 并且在发射时不起作用(正如我在回答中所写的那样)。现在,我正试图弄清楚为什么从您的异常处理程序进行广播不起作用:)
    • 让它工作@mccainz - 我已经用工作代码sn-p更新了我的答案。
    • 依赖注入 $injector 成功了。 $emit 现在可以按预期工作了($broadcst 与 $emit 不是问题)。我很好奇的是,使用 ng->Injector 与 $injector 作为依赖项导致的 $rootScopes 之间到底有什么区别。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2018-06-23
    • 2013-11-24
    • 2012-12-12
    • 2018-12-04
    • 2014-03-07
    • 2020-10-11
    • 2013-01-05
    • 1970-01-01
    相关资源
    最近更新 更多