从事件

时间:2015-08-04 09:48:41

标签: javascript angularjs angularjs-directive

我在Angular的指令中遇到了一个我根本不理解的奇怪行为;让我用代码解释它,我认为这是最简单的方法。

工作原理:

.directive('myDirective', function ($http) {
    return {
        template: '...',
        link: function (scope, elem, attrs) {
            function getData() {
                console.log('Starting...');
                $http.get(...).success(/* update the template */);
            }
            getData();
        }
    };
});

什么不是:

.directive('myDirective', function ($http) {
    return {
        template: '...',
        link: function (scope, elem, attrs) {
            function getData() {
                console.log('Starting...');
                $http.get(...).success(/* update the template */);
            }
            scope.$on('callMyDirective', getData);
        }
    };
});

第二个例子中完全忽略了$ http调用,甚至没有在promise的finally()部分打印一个东西(确实没有网络活动),而在两种情况下都正确打印了日志(在第二种情况,当然,在触发事件后,点击按钮)。

有任何线索吗?

非常感谢。

更新

我找到了错误的来源,但这又是另一个问题。问题是我有一个拦截器,我在其中包装所有请求,但是应该使用promise来验证用户,我只在验证结束时解析。所以我的拦截器看起来像这样:

request: function (config) {
    if (userHasArrived || isAuthUrl) {
        return config || $q.when(config);
    }

    var defer = $q.defer();

    $rootScope.$on('user_logged_in', function (user) {
        console.log('User logged in');
        userHasArrived = true;
        defer.resolve(config);
    });
    return defer.promise;
}

同时,我有一个运行auth请求的服务,并在成功时广播上面显示的事件。这适用于所有其他请求,但对于我有上面提到的指令,它在不同的"页面",并且永远不会在Interceptor中接收事件(日志永远不会被打印)。

只有当我向我的" auth"强制第二次请求时URL,接收事件,指令内容可以正常工作。可能是在拦截器之前以某种方式加载了服务?在这种情况下,有没有办法控制这个加载顺序?

更新

好的,抱歉打扰你,但如果有人仍然感兴趣,我找到了第二个问题的解决方案。这就是事情发生的顺序:

  1. 身份验证请求启动
  2. 认证请求结束,广播成功
  3. 指令请求启动(按需,单击按钮)
  4. 认证成功开始被听取
  5. 所以在有人听之前,事件被解雇了。这将是最终的代码(它的不完整版本):

    $rootScope.$on('user_logged_in', function (user) {
        userHasArrived = true;
    });
    
    return {
        request: function (config) {
            if (userHasArrived || isAuthUrl) {
                return config || $q.when(config);
            }
    
            var defer = $q.defer();
    
            var $off = $rootScope.$on('user_logged_in', function (user) {
                userHasArrived = true;
                $off(); // You better unsubscribe for the events too, if you do something along this lines
                defer.resolve(config);
            });
            return defer.promise;
        }
    };
    

1 个答案:

答案 0 :(得分:0)

我希望这有效

.directive('myDirective', function ($http) {
    return {
        template: '...',
        link: function (scope, elem, attrs) {
             scope.getData = function () {
                console.log('Starting...');
                $http.get(...).success(/* update the template */);
            }
            scope.$on('callMyDirective', function (event, args) {
              scope.getData();
            });
        }
    };
});

或其他替代

.directive('myDirective', function ($http) {
    return {
        template: '...',
        link: function (scope, elem, attrs) {
            var _this = this;
            function getData() {
                console.log('Starting...');
                $http.get(...).success(/* update the template */);
            }
            scope.$on('callMyDirective', function (event, args){
               $scope.$apply(function (){
                 _this.getData();
               })
             });
        }
    };
});