使用 angular 指令会导致错误:达到 10 次 $digest() 迭代。中止
Posted
技术标签:
【中文标题】使用 angular 指令会导致错误:达到 10 次 $digest() 迭代。中止【英文标题】:Using angular directive causes error: 10 $digest() iterations reached. Aborting 【发布时间】:2016-11-15 08:11:25 【问题描述】:http://plnkr.co/edit/dBe36L6vwOZOykujFRfg
在 plunker 中,我收到以下角度错误:“已达到 10 个 $digest() 迭代。正在中止!”
该逻辑在 index.html 中使用时有效:
<h1>(working) Fruit from main document: vm.randomFruit().name</h1>
但是当我尝试使用传入的对象调用指令中的类似代码时抛出错误:
<h1>(causing error) Fruit from directive template: fruit.name</h1>
如果我只是在范围函数中执行此操作,它似乎也不会在指令中引发错误:
//this works for both instances
return vm.fruits[0];
但是,当我以任何方式触摸 $scope.fruits 时,即使只是复制它,它也会在指令版本上出现错误。
//something about touching the array here exposes the error, even though it still works
var x = [];
angular.copy(vm.fruits, x);
return x[0];
为什么这里会抛出这个错误?似乎是某种循环依赖,但为什么只在指令版本上呢?
有没有更好的方法来使用更标准的指令、模板和传入的参数对象?
错误:达到 10 次 $digest() 迭代。中止!观察者开枪 最后 5 次迭代: [["fn: parentValueWatch; newVal: \"名称\":\"苹果\"; oldVal: \"name\":\"apple\""],["fn: 父值观察; newVal: \"名称\":\"苹果\";旧值: \"name\":\"apple\""],["fn: parentValueWatch;新值: \"名称\":\"苹果\"; oldVal: \"name\":\"apple\""],["fn: 父值观察; newVal: \"名称\":\"苹果\";旧值: \"name\":\"apple\""],["fn: parentValueWatch;新值: \"名称\":\"苹果\"; oldVal: \"name\":\"apple\""]] 在错误(本机) 在 Object.$digest (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:7925:19) 在 Object.$apply (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:8097:24) 完成后 (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:9111:20) 在完成请求 (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:9274:7) 在 XMLHttpRequest.xhr.onreadystatechange (https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js:9244:11)
更新 1
将 aFruit() 更新为 randomFruit() 以便更好地展示我的问题:
$scope.randomFruit = function()
//something about touching the array here exposes the error, even though it still works
var x = [];
angular.copy($scope.fruits, x);
//do some custom stuff here, sorting, etc. <whatever>
var randomIndex = Math.floor((Math.random() * x.length));
return x[randomIndex];
;
更新 2
被告知不要使用 $scope,因此将其从控制器中完全删除。仍然看到同样的错误。
myApp.controller('FruitCtrl', function()
var vm = this;
vm.fruits = fruits;
vm.randomFruit = function()
//something about touching the array here exposes the error, even though it still works
var x = [];
angular.copy(vm.fruits, x);
//do some custom stuff here, sorting, etc. <whatever>
var randomIndex = Math.floor((Math.random() * x.length));
return x[randomIndex];
;
);
【问题讨论】:
【参考方案1】:问题在于方法,如何将数据传递给 Angular。 Angular 有很棒的数据绑定,它会检查模型是否改变并更新 UI。更新 UI 后,它会再次检查下一轮更改。如果数据一直在变化,它可能会卡在循环中。
在这种特殊情况下,Angular 不理解数据是相同的。它在每个摘要循环中接收新数组并假定数据已更改,更新 UI 并再次开始检查。
确保您没有在每个 $digest 循环中从 UI 更新数组或在每个 $digest 循环上返回新数组。 例如 这将调用无限循环:
$scope.aFruit= function()
return [
"name":"apple",
"name":"orange",
"name":"banana",
];
;
这将正常工作,因为对数组的引用保持不变
var myFruits = return [
"name":"apple",
"name":"orange",
"name":"banana",
]
$scope.aFruit= function()
myFruits;
;
【讨论】:
JanisP 是正确的,这就是我假设你想要它做的事情:plnkr.co/edit/cFchj9uxVZRj5Fe8L5Al?p=preview 另外,我建议您查看 Angular 1.5 中的新组件方法,这是更简洁的指令。 plnkr.co/edit/7leRr2TfoVOSfdVjxNK0?p=preview @hsiung - 不,简单地返回第一个元素不是我的意思。这是一个更复杂的函数,例如从数组中返回一个随机元素或对数组进行排序并从中返回顶部哦,好的,明白了! 有两种方法可以做到这一点,但我相信您正在寻找这种方法。
http://plnkr.co/edit/E1y9nqh0DdaHGW2hi4AM?p=preview
问题是您的方法正在返回一个对象,但您想获取字符串值。所以我们把方法改成这样:
$scope.randomFruit = function()
var x = [];
angular.copy($scope.fruits, x);
var randomIndex = Math.floor((Math.random() * x.length));
return x[randomIndex].name;
;
接下来,我们需要更改我们的组件绑定以接受带有“@”的字符串
bindings: fruit: '@' ,
最后,我们需要调用模板中的方法,并使用插值将其设置为我们传递给组件的值:
<show-fruit fruit=randomFruit() />
希望这会有所帮助,还有另一种方法,但是如果您想在 in 模板中调用您的方法,这就是您必须这样做的方式。
【讨论】:
不错的尝试,但我想将整个对象传递给模板,而不仅仅是属性之一。我知道模板现在只使用“名称”属性,但这是一个非常简化的示例,说明我正在尝试在另一个项目中使用我的代码库。 好的,所以如果您尝试传入整个对象,则无法复制它。这就是贾尼斯最初所说的。您在每个摘要周期都生成一个新对象,因此 angular 不知道何时停止。 - 您可以使用 '&' 绑定传递函数并在指令中调用函数 - 在控制器中调用函数并将输出分配给范围变量,然后将该新对象传递给指令 - 您可以执行 Janis 的操作做了并将逻辑放在指令中 - 或者您可以对原始集合进行操作(即不要复制它)以上是关于使用 angular 指令会导致错误:达到 10 次 $digest() 迭代。中止的主要内容,如果未能解决你的问题,请参考以下文章
Angular 2 编写结构指令,如 ngFor、iterableDiffer 可能会导致错误
Angular2-signaturepad 与 Angular 一起使用会导致找不到模块错误
如何解决 Angular “10 $digest() 迭代次数达到”错误
Angular JS:IE 错误:达到 10 次 $digest() 迭代。中止