【问题标题】:Why is my watcher giving me a "Infinite $digest Loop" error?为什么我的观察者给我一个“无限 $digest 循环”错误?
【发布时间】:2015-09-26 06:20:47
【问题描述】:

我在使用 watcher 函数时遇到了一个奇怪的问题:

$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

我不确定如何避免这种情况。谁能帮帮我?

【问题讨论】:

  • 删除“builder.editItemForm.quantity”上的观察者后。我再次遇到错误...不确定哪个观察者...

标签: angularjs angularjs-watch


【解决方案1】:

因为您要在手表内更改您的值 builder.editItemForm.quantity ,它将再次运行摘要循环并在值更改时始终触发手表。在您的情况下,您正在更改手表内部的值,这将陷入无限循环。

说明

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

例如,通过在路径上设置监视并随后在值更改时更新同一路径时,可能会发生这种情况。

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

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

【讨论】:

  • 先不要保留builder.editItemForm.quantity = newValue;因为已经分配了新值,所以您不需要手动进行。它会解决您的问题。
  • 我试图停止在输入类型数字的文本框中输入奇数。除了手表还有什么更好的方法来实现这一点?
  • 你可以创建一个过滤器。
  • 使用 ng-model-options getter setter
【解决方案2】:

一种解决方法是通过watch,设置数量后尝试注销watch。它会工作一次。 另一件事是使用 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2016-07-21
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    相关资源
    最近更新 更多