我正在努力创建一个指令。事情根本就没有用,所以我简化了事情,直到我发现这个基本的竞争条件问题给我带来了问题。在我的指令控制器中,我需要做一些检查,比如......
if ($scope.test.someValue === true) { $scope.test.anotherValue += 1; }
这是我的基本指令,其中包含一些日志,用于说明此问题的显示方式。
app.directive('myDirective', function () {
return {
restrict: 'E',
replace: true,
scope: {
test: '='
},
template: '<div><pre>{{ test | json }}</pre></div>',
controller: function ($scope, $timeout) {
// this logs undefined
console.log($scope.test);
// this logs the scope bound 'test' object
$timeout(function() {
console.log($scope.test);
}, 300);
}
};
});
使用这种竞争条件的正确方法是什么?我担心在现实世界中,这个超时功能会根据api调用的时间长短而起作用。
答案 0 :(得分:4)
请记住在&#34;链接&#34;阶段(当您分配控制器时),尚未分配$scope.test
变量 - 因此undefined
$timeout(fn, timeout)
是一种执行会影响$ scope内容的方法。您可以将$ timeout()值设置为0,它仍然可以工作。这是因为$ timeout(...)函数将推迟到当前$digest()
周期之后。
<强>参考文献:强> $timeout() $digest()
此外,如果您想观察特定值的变化,您可以这样做:
$scope.$watch("test.somevalue", function(new_val, old_val) {
console.log("somevalue changed!! - increment othervalue");
$scope.othervalue += 1;
});
答案 1 :(得分:1)
控制器在预链接阶段(当指令的范围尚未绑定到任何父范围时)实例化。
控制器是您放置指令的业务逻辑的地方。
任何初始化代码(尤其是依赖于与父作用域绑定的代码)都应该在链接阶段运行(即使用指令定义对象的link
属性)。
app.directive('myDirective', function () {
return {
restrict: 'E',
replace: true,
scope: {
test: '='
},
template: '<div><pre ng-click="someFunc()">{{ test | json }}</pre></div>',
controller: function ($scope) {
/* No two-way bindings yet: test -> undefined */
/* Business logic can go here */
$scope.someFunc = function () {
alert('I implement the business logic !');
};
},
link: function postLink(scope, elem, attrs) {
/* Bindings are in place. Safe to check up on test. */
console.log($scope.test);
}
};
});
答案 2 :(得分:0)
使用Race条件的一种方法是$watch要使用的变量,当它的值更改为您想要的值(在您的情况下为!= undefined
)时,您可以使用该变量。需要观察的表达式每$digest
个周期进行一次评估。以下是您的案例示例:
$scope.$watch('test', function(val){
if(val != undefined) {
if ($scope.test.someValue === true) { $scope.test.anotherValue += 1; }
}
})