为什么我的观察者给我一个“Infinite $ digest Loop”错误?

时间:2015-07-08 11:13:02

标签: angularjs angularjs-watch

我在观察者功能方面遇到了一个奇怪的问题:

$scope.$watch('builder.editItemForm.quantity',function(newValue,oldValue){
    if(newValue !== oldValue){
        if(newValue % 2 == 0){
            builder.editItemForm.quantity = newValue;
        } else {
            builder.editItemForm.quantity = oldValue;
        }
    }
});

我收到此错误:

Error: $rootScope:infdig Infinite $digest Loop

10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["builder.editItemForm.quantity;     newVal: 1; oldVal: undefined"],["builder.editItemForm.quantity; newVal: undefined; oldVal: 1"],["builder.editItemForm.quantity; newVal: 1; oldVal: undefined"],["builder.editItemForm.quantity; newVal: undefined; oldVal: 1"],["builder.editItemForm.quantity; newVal: 1; oldVal: undefined"]]

https://docs.angularjs.org/error/$rootScope/infdig?p0=10&p1=%5B%5B%22builder.editItemForm.quantity;%20newVal:%201;%20oldVal:%20undefined%22%5D,%5B%22builder.editItemForm.quantity;%20newVal:%20undefined;%20oldVal:%201%22%5D,%5B%22builder.editItemForm.quantity;%20newVal:%201;%20oldVal:%20undefined%22%5D,%5B%22builder.editItemForm.quantity;%20newVal:%20undefined;%20oldVal:%201%22%5D,%5B%22builder.editItemForm.quantity;%20newVal:%201;%20oldVal:%20undefined%22%5D%5D

我不确定如何避免这种情况。任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:0)

因为您要在手表中更改值 builder.editItemForm.quantity ,这将再次运行摘要周期,并在值更改时始终触发。在你的情况下,你正在改变你在观察中的价值,这将成为无限循环。

<强>描述

当应用程序的模型变得不稳定并且每个$摘要周期触发状态更改和随后的$摘要周期时,会发生此错误。 Angular检测到这种情况并防止无限循环导致浏览器无响应。

例如,可以通过在路径上设置监视并随后在值更改时更新相同路径来实现这种情况。

$scope.$watch('foo', function() {
  $scope.foo = $scope.foo + 1;
});

参考文档 https://docs.angularjs.org/error/$rootScope/infdig

答案 1 :(得分:0)

一种解决方案是通过观察并在设定数量后尝试取消注册。它会工作一次。 另一件事是使用ng-model-options getterSetter,它将与watch事件相同。

1) 在某些情况下,您可以取消注册观看事件。 在您的控制器中:

$scope.$watch('updated', function(newValue,oldValue){
      $scope.stop();
});
$scope.stop = $scope.$watch('builder.editItemForm.quantity',function(newValue,oldValue){
        if(newValue !== oldValue){
            if(newValue % 2 == 0){
                builder.editItemForm.quantity = newValue;
                $scope.updated = true;
            }
            else
            {
                builder.editItemForm.quantity = oldValue;
                $scope.updated = true;
            }
        }
    });

$ scope。$ watch返回调用时的函数,停止观看,这称为取消注册。它在这里仍然是重​​复使用,但可能有效。

另一个更通用的解决方案是使用ng-model-options getter和setter。 在您的视图中使用:

ng-model="quantity" ng-model-options="{ getterSetter: true; }"

并在控制器define getter and setter中: