我在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,接收事件,指令内容可以正常工作。可能是在拦截器之前以某种方式加载了服务?在这种情况下,有没有办法控制这个加载顺序?
更新
好的,抱歉打扰你,但如果有人仍然感兴趣,我找到了第二个问题的解决方案。这就是事情发生的顺序:
所以在有人听之前,事件被解雇了。这将是最终的代码(它的不完整版本):
$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;
}
};
答案 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();
})
});
}
};
});