Angularjs 在没有超时函数的情况下,如何克服指令内的竞争条件?

Angularjs 在没有超时函数的情况下,如何克服指令内的竞争条件?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我正在尝试创建一个指令。事情根本不起作用,所以我简化了事情,直到我发现这个基本的比赛条件问题给我带来了问题。在我的指令控制器中,我需要做一些检查,如 if ($scope.test.someValue === true) { $scope.test.anotherValue += 1; } 下面是我的基本指令和一些日志,以说明这个问题是如何表现出来的 app.directive('myDirective', function () { return { restrict

我正在尝试创建一个指令。事情根本不起作用,所以我简化了事情,直到我发现这个基本的比赛条件问题给我带来了问题。在我的指令控制器中,我需要做一些检查,如

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);

        }
    };
});
app.directive('myDirective',函数(){
返回{
限制:'E',
替换:正确,
范围:{
测试:'='
},
模板:“{test | json}}”,
控制器:函数($scope,$timeout){
//此日志未定义
log($scope.test);
//这将记录范围绑定的“测试”对象
$timeout(函数(){
log($scope.test);
}, 300);
}
};
});
在这种比赛条件下,正确的工作方式是什么?我担心在现实世界中,此超时函数会根据api调用所需的时间而工作或失败。

请记住,在“链接”阶段(分配控制器时),尚未分配
$scope.test
变量-因此
未定义

$timeout(fn,timeout)
是一种执行将影响$scope中某些内容的方法。您可以将$timeout()值设置为0,它仍然可以工作。这是因为$timeout(…)函数将延迟到当前
$digest()
周期之后

参考文献:

此外,如果要查看特定值的更改,可以执行以下操作:

$scope.$watch('test', function(val){
    if(val != undefined) {
        if ($scope.test.someValue === true) { $scope.test.anotherValue += 1; }
    }
})

处理竞争条件的一种方法是使用您想要使用的变量,当其值更改为您想要的值时(
!=undefined
,在您的情况下),您可以使用该变量。每个
$digest
周期对需要监视的表达式求值。以下是您案例的一个示例:

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

控制器在预链接阶段实例化(当指令的作用域尚未绑定到任何父作用域时)

控制器是放置指令的业务逻辑的地方

任何初始化代码(特别是依赖于父范围绑定的代码)都应该在链接阶段运行(即使用指令定义对象的
link
属性)

app.directive('myDirective',函数(){
返回{
限制:'E',
替换:正确,
范围:{
测试:'='
},
模板:“{test | json}}”,
控制器:功能($scope){
/*还没有双向绑定:测试->未定义*/
/*业务逻辑可以放在这里*/
$scope.someFunc=函数(){
警报(“我实现了业务逻辑!”);
};
},
链接:函数postLink(范围、元素、属性){
/*绑定到位。测试时可以安全检查*/
log($scope.test);
}
};
});

这很有道理。从link函数设置控制器值是否简单?例如,基于您上面的示例。如果控制器包含$scope.someConstant=null;然后,我是否可以在链接函数$scope.someConstant=$scope.test.someProperty;中包含该值,从而在链接函数初始化时更新该值?或者这两个函数之间的通信是如何工作的?是的,注入控制器的
$scope
和传递给链接函数的
scope
参数是相同的。更新一个位置的值也会更新另一个位置的值(因为它是同一个对象)。@Constellates:我不是故意的!@#$%,但公认的答案不是“在这种比赛条件下正确的工作方式”。(并不是说我很在乎——只是说……)不用担心,我对定制指令还是新手,所以我不能总是解读什么是最佳实践。虽然我仍然有相同的种族问题与你的解决方案。链接函数中的console.log未定义日志记录。如果我把它放在$scope中。$watch在link函数中,它会再次工作。@Constellates:也许我搞错了什么,因为它似乎是。不过,你的意思可能有所不同。
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);
        }
    };
});