How to Loop through items returned by a function with ng-repeat?

I want to create divs repeatedly, the items is objects returned by a function. However the following code report errors: 10 $digest() iterations reached. Aborting! jsfiddle is here: http://jsfiddle.net/BraveOstrich/awnqm/

<body ng-app>
<div ng-repeat="entity in getEntities()">
Hello {{entity.id}}!
</div>
</body>
90438 次浏览

这是 在这里报道,得到了这样的回答:

您的 getter 不是幂等的,并且更改了模型(通过每次调用时生成一个新数组)。这迫使角度继续调用它,希望模型最终能够稳定下来,但它从来没有这样做过,角度放弃了,抛出了一个例外。

Getter 返回的值相等但不相同,这就是问题所在。

如果将数组移到 Main 控制器之外,可以看到这种行为消失了:

var array = [{id:'angularjs'}];
function Main($scope) {
$scope.getEntities = function(){return array;};
};

因为现在它每次都返回相同的对象。您可能需要重新架构您的模型,使用作用域上的属性而不是函数:

We worked around it by assigning the result of the controller's method to a property, and doing ng:repeat against it.

简短的回答 : 你真的需要这样的函数吗,或者你可以使用属性吗? < a href = “ http://jsfiddle.net/awnqm/1/”rel = “ norefrer”> http://jsfiddle.net/awnqm/1/

答案很长

为了简单起见,我将只描述 case-ng 对对象数组进行重复。

AngularJS 使用 $rootScope5来检测变化。当应用程序启动时,它为 $rootScope7运行 $rootScope6。$digest将对 $rootScope8进行深度优先遍历。所有望远镜都有手表清单。每块表都有最后一个值(最初是 initWatchVal)。对于所有手表的每个范围,$digest运行它,获取当前值(watch.get(scope))并将其与 watch.last进行比较。如果当前值不等于 watch.last(总是首先比较) ,$digestdirty设置为 $rootScope0。如果 $rootScope1$digest$rootScope开始另一次深度优先遍历,则在处理所有作用域时。当脏 = = false 或遍历次数 = = 10时,$digest结束。在后一种情况下,出现了错误“达到了10美元摘要()迭代”将被记录。

现在谈谈 ngRepeat。对于每个 watch.get调用,它存储收集到的对象(返回值为 getEntities)和缓存中的附加信息(HashQueueMaphashKey)。对于每个 watch.get调用 ngRepeat尝试通过其 hashKey从缓存获取对象。如果在缓存中不存在,则 ngRepeat将其存储在缓存中,创建新的作用域,在其上放置对象,创建 DOM 元素 watch.get0。

现在谈谈 hashKey。通常 hashKey是由 nextUid()产生的唯一数字。但也可以是 功能hashKey在生成后存储在对象中,以备将来使用。

Why your example generates error: function getEntities() always returns array with new object. This object doesn't have hashKey and doesn't exist in ngRepeat cache. So ngRepeat on each watch.get generates new scope for it with new watch for \{\{entity.id}}. This watch on first watch.get has watch.last == initWatchVal. So watch.get() != watch.last. So $digest starts new traverse. So ngRepeat creates new scope with new watch. So ... after 10 traverses you get error.

你怎么能修好它

  1. 不要在每个 getEntities()调用上创建新对象。
  2. 如果需要创建新对象,可以为它们添加 hashKey方法。

希望了解 AngularJS 内部机制的人会纠正我的错误。

初始化重复之外的数组

<body ng-app>
<div ng-init="entities = getEntities()">
<div ng-repeat="entity in entities">
Hello \{\{entity.id}}!
</div>
</div>
</body>

基于@przno 评论

<body ng-app>
<div ng-repeat="item in t = angular.equals(t, getEntities()) ? t : getEntities()">
Hello \{\{item.id}}!
</div>
</body>

顺便说一句,阿尔特姆 · 安德烈夫建议的第二种解决方案不适用于角度1.1.4或更高的情况,而第一种解决方案不能解决问题。因此,我担心现在这是一个不那么尖锐的解决方案,在功能上没有缺点