10 $ digest()迭代到达。中止! jsfiddle在这里: http://jsfiddle.net/BraveOstrich/awnqm/
<body ng-app> <div ng-repeat="entity in getEntities()"> Hello {{entity.id}}! </div> </body>
答案很长
为了简单起见,我将仅描述您的情况 – 对象数组的ngRepet。此外,我会省略一些细节。
AngularJS使用dirty checking来检测更改。当应用程序启动时,它运行$digest
为$rootScope
. $ digest将做深度优先遍历为scope’s hierarchy.所有范围有手表的列表。每个watch都有最后一个值(最初是initWatchVal)。对于所有手表的每个范围$ digest运行它,获取当前值(watch.get(scope)),并将其与watch.last进行比较。如果当前值不等于watch.last(总是为第一次比较)$ digest设置脏为true。当所有作用域被处理,如果dirty == true $ digest启动另一个深度优先遍历$ rootScope。 $ digest在dirty == false或遍历数10时结束。在后一种情况下,错误“10 $ digest()iterations reached。将被记录。
现在关于ngRepeat。对于每个watch.get调用它存储对象从收集(返回值的getEntities)与缓存中的附加信息(HashQueueMap
由hashKey)。对于每一个watch.get调用ngRepeat尝试从其缓存中的hashKey获取对象。如果它不存在于缓存中,ngRepeat将其存储在缓存中,创建新范围,在其上放置对象,创建DOM元素,etc。
现在约hashKey
.通常hashKey是由nextUid()
生成的唯一编号。但它可以是function. hashKey在生成后存储在对象中以供将来使用。
为什么你的示例生成错误:function getEntities()总是返回带有新对象的数组。此对象没有hashKey,并且不存在于ngRepeat缓存中。所以ngRepeat在每个watch.get生成新的范围为它新的手表{{entity.id}}。这个watch在第一个watch.get有watch.last == initWatchVal。所以watch.get()!= watch.last。所以$ digest开始新的遍历。所以ngRepeat用新的手表创建新的范围。所以… 10遍之后你会得到错误。
如何解决它
>不要在每次getEntities()调用时创建新对象。
>如果你需要创建新对象,你可以为它们添加hashKey方法。参见this topic的例子。
希望知道AngularJS内部的人纠正我,如果我错了什么。