Angular - 达到 10 次 $digest() 迭代。创建数组的深层副本时中止
Posted
技术标签:
【中文标题】Angular - 达到 10 次 $digest() 迭代。创建数组的深层副本时中止【英文标题】:Angular - 10 $digest() iterations reached. Aborting when creation deep copy of array 【发布时间】:2017-09-02 08:47:10 【问题描述】:我想在表格标题中创建带有过滤器的表格。过滤器是每列中唯一值的列表。这是简化的代码:
<table>
<tr>
<th class="dropdown" ng-repeat="field in data.columns">
<span>field.title</span>
<ul class="dropdown-menu">
<li ng-repeat="item in unique(data.items, field)"><checkbox> item.text</li>
</ul>
</th>
</tr>
<tr ng-repeat="item in data.items"></tr>
</table>
我对过滤器和表使用相同的对象数组,但过滤器创建数组的副本并从重复的副本值中删除。这是我的问题。
当我将数组复制为array.slice(0)
时,删除的值不在过滤器中,而是在表中(数组包含对象)。我的问题出在引用中,所以我使用 deepcopy 作为 jQuery.extend(true, [], array)
并且 angular throws 错误:
[$rootScope:infdig] 达到 10 次 $digest() 迭代。中止! 在最后 5 次迭代中触发的观察者
我的数据如下所示:
[id: 1, title: 'AAA', something: [id: 1, text: "A"], id: 2, title: 'AAAA', something: [id: 2, text: "AA"]]
问题出在属性上(array.slice(0)
donť 复制和 $.extend 复制但 angular get 错误)
感谢您的建议
【问题讨论】:
angular.copy()
角度方式。
我认为如果您将一些操作数组的逻辑移至控制器,您的问题就会消失。尝试将对 unique(data.items, field) 的调用移动到控制器函数。如果您可以减少其中一个 ng-repeat,那将显着减少摘要循环的数量。
另一种角度方法可能是使用 $filter('filter') 或为 ng-repeat 创建自定义过滤器。
【参考方案1】:
您还没有发布过滤器的代码,所以我必须假设发生了什么。我认为您没有在制作副本之前检查列表的所有元素是否都是唯一的。这会导致过滤器更改数据每个摘要,从而触发无限数量的摘要 - 因此出现错误。你的名单永远不稳定。
要在过滤器开始时解决这个问题,请添加检查元素的唯一性,如果它们已经是唯一的(例如在第一次通过过滤器之后),只需返回输入对象。这样模型就会稳定下来。
【讨论】:
【参考方案2】:这是我从对象数组中获取唯一值的代码:
function toUnique(a, property, innerProperty)
var lastIndex = a.length;
if (lastIndex === 0 || lastIndex === undefined)
return a;
var copyarr = jQuery.extend(true, [], a);
if (property !== undefined)
while (prevIndex = --lastIndex)
while (prevIndex--)
var obj1 = copyarr[lastIndex];
var obj2 = copyarr[prevIndex];
if (obj1 !== undefined)
if (copyarr[lastIndex][property] instanceof Array && copyarr[prevIndex][property] instanceof Array)
unique(copyarr[lastIndex][property], copyarr[prevIndex][property], innerProperty);
else
obj1[property] !== obj2[property] || copyarr.splice(prevIndex, 1);
return copyarr;
else
while (prevIndex = --lastIndex)
while (prevIndex--)
copyarr[lastIndex] !== copyarr[prevIndex] || copyarr.splice(prevIndex, 1);
return copyarr;
function unique(array1, array2, innerProperty)
for (var i = 0; i < array1.length; i++)
removeDuplicates(array1, i + 1, array1[i], innerProperty);
removeDuplicates(array2, 0, array1[i], innerProperty);
for (var i = 0; i < array2.length; i++)
removeDuplicates(array2, i + 1, array2[i], innerProperty);
function removeDuplicates(arr, startPos, p, property)
for (var i = startPos; i < arr.length;)
if (p[property] == arr[i][property])
arr.splice(i, 1);
else
i++;
使用:
var a = [id: 1, title: "AAAA", id: 2, title: "BBBB", id: 1, title: "AAAA"]
unique(a, "title", null); //return id: 1, title: "AAAA", id: 2, title: "BBBB"
var b = [id: 1, title: "AAAA", authors: [id: 15, name: "John", id: 25, name: "Peter", id: 16, name: "John"],
id: 1, title: "BBBB", authors: [id: 15, name: "John", id: 25, name: "Peter]]
unique(b, "authors", "name") //return: [id: 1, title: "AAAA", authors: [id: 15, name: "John", id: 25, name: "Peter],
id: 1, title: "BBBB", authors: []]
【讨论】:
检查if (lastIndex === 0 || lastIndex === undefined)
后,还要检查所有元素是否已经唯一,如果是,返回a
。您也可以考虑使用 linq.js
或 lodash
这样的库,其中已经实现了唯一检查。以上是关于Angular - 达到 10 次 $digest() 迭代。创建数组的深层副本时中止的主要内容,如果未能解决你的问题,请参考以下文章
Angular - 达到 10 次 $digest() 迭代。创建数组的深层副本时中止
如何解决 Angular “10 $digest() 迭代次数达到”错误
ng-repeat:达到 10 次 $digest() 迭代