如何在没有超时功能的情况下克服指令中的竞争条件?

时间:2014-05-24 18:00:38

标签: angularjs angularjs-directive

我正在努力创建一个指令。事情根本就没有用,所以我简化了事情,直到我发现这个基本的竞争条件问题给我带来了问题。在我的指令控制器中,我需要做一些检查,比如......

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调用的时间长短而起作用。

3 个答案:

答案 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; }
    }
})