尽管进行了相同的检查,但是过于频繁地调用ng $ watch

时间:2014-10-25 06:55:29

标签: angularjs

我定义了2个控制器。一个创建一个列表,另一个(嵌套)使用它。 我正在使用$ watch(' listname',function,true)以及明确防范重复项, 但是(1)手表被多次击中,(2)有些时候完全相同的旧/新。 我想知道我做错了什么。

myApp.controller("ovcMainCtlr", [ "$scope", "$http", function($scope, $http){
    //...
    $scope.toggleVPCSelection = function(vpc_id) {
        assert(vpc_id in $scope.gVPCList, "missing vpc_id=" + vpc_id + " in the list?");
        $scope.gVPCList[vpc_id].selected = ! $scope.gVPCList[vpc_id].selected;
        $scope.gSelectedVPCList = _.sortBy( _.pluck(_.filter( $scope.gVPCList, {selected:true} ), "id" ) );
    };
}]);

和第二个:

myApp.controller("ovcServerCtlr", [ "$scope", "$http", function($scope, $http){
    //...
    $scope.$watch('gSelectedVPCList', function(newval, oldval){
        console.log("watch! new vpc sel=", newval, "old=", oldval);
        if ( newval && newval.length && ! angular.equals(newval, oldval) ) {
            _refreshServerList(newval);
        }
    }, true);
}]);

HTML

<body ng-controller="ovcMainCtlr">
    <div class="panel">
        <span>Select VPC Filter >>></span>
        <span class="vpc-selector" ng-repeat="vpc in vpcList()">
            <input type="checkbox" name="vpc" value="vpc.id" ng-checked="vpc.selected"
                   ng-click="toggleVPCSelection(vpc.id)">
            {{ vpc.id + " / " + vpc.name }}
        </span>
    </div>
    <hr/>
    <div ng-repeat="vpc in gSelectedVPCList" ng-controller="ovcServerCtlr">
        I can see a selected {{ vpc | json }}
    </div>
    ...

控制台说,当我点击修改gSelectedVPCList,然后检查等于

  watch! new vpc sel= ["v1-123456789", "v2-4567"] old= ["v1-123456789"] serverCtlr.js:31
  watch! new vpc sel= ["v1-123456789", "v2-4567"] old= ["v1-123456789"] serverCtlr.js:31
  watch! new vpc sel= ["v1-123456789", "v2-4567"] old= ["v1-123456789", "v2-4567"] serverCtlr.js:31
> angular.equals( ["v1-123456789", "v2-4567"], ["v1-123456789", "v2-4567"] )
  true

感谢。

- 编辑,$ watch更改为angular.equals()而不是!== !!但问题的其余部分仍然是相同的

1 个答案:

答案 0 :(得分:2)

这是因为$diggest周期而发生的。

每次角度进入$diggest周期时,$diggest周期将评估$watch的所有$scope函数。

$diggest周期是Angular确保模型更改已解决的阶段, 这样它就可以使用更新的更改呈现视图。为了做到这一点, Angular启动一个循环,其中每次迭代都会计算所有模板表达式 视图,以及$watcher的{​​{1}}函数。 如果在当前迭代中结果与前一个结果相同, 然后Angular将退出循环。否则,它会再试一次。 如果在10次尝试之后事情还没有解决,Angular将退出 错误:"Infite $diggest Loop Error" (infdig)

此图可能有助于您了解Angular如何在幕后工作:

enter image description here

(我借鉴了here