我设法创建一个开箱即用的小样本,可以重现问题。它是一个过滤器,可以从数组中随机删除2个元素:
<!DOCTYPE html>
<html ng-app='myApp'>
<head>
<meta charset="utf-8" />
<script src="https://code.angularjs.org/1.6.5/angular.js"></script>
<script>
angular.module('myApp', [])
.filter('random', function() {
return function(input) {
var a = Math.floor(Math.random()*input.length);
var b = Math.floor(Math.random()*input.length);
return input.filter(function(element, i){
if (i !== a && i !== b){
return element;
}
});
};
})
.controller('Controlleur', function($scope) {
$scope.contacts = [
{"name": "donatello", "tel": 12456},
{"name": "michaelangelo", "tel": 12456},
{"name": "leonardo", "tel": 12456},
{"name": "raphael", "tel": 12456},
{"name": "robert", "tel": 12456},
]
});
</script>
</head>
<body ng-controller="Controlleur">
<ul>
<li ng-repeat="contact in contacts|random track by contact.name ">
<strong>{{contact.name}}</strong>: {{contact.tel}}
</li>
</ul>
</body>
</html>
将其复制/粘贴到文件中,在浏览器中加载文件,然后打开控制台。如果您按F5几次,您会看到过滤器有效,但您会随机获得:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [[{"msg":"fn: regularInterceptedExpression","newVal":21,"oldVal":18},{"msg":"fn: regularInterceptedExpression","newVal":"raphael"},{"msg":"fn: regularInterceptedExpression","newVal":"12456"},{"msg":"fn: regularInterceptedExpression","newVal":"robert"},{"msg":"fn: regularInterceptedExpression","newVal":"12456"}],
...
问题在于它通常意味着连续多次触发$ digest。但是,我不会在任何地方明确更新范围。我只是在过滤器中创建一个新阵列,副作用非常明显。
答案 0 :(得分:2)
由于你在每个摘要中返回数组中的随机项,因此范围永远不会稳定(每次都是相同的数组)并且继续进行摘要寻找它以稳定它然后它会达到它的限制和中止。
修复方法是在控制器中使用$filter()
进行一次随机化,然后再传递新的已过滤数组以查看并删除视图中的随机过滤器
.controller('Controlleur', function($scope, $filter) {
$scope.contacts = [
{"name": "donatello", "tel": 12456},
{"name": "michaelangelo", "tel": 12456},
{"name": "leonardo", "tel": 12456},
{"name": "raphael", "tel": 12456},
{"name": "robert", "tel": 12456},
];
$scope.randomContacts = $filter('random')($scope.contacts);
});
查看:
<li ng-repeat="contact in randomContacts track by contact.name ">
<strong>{{contact.name}}</strong>: {{contact.tel}}
</li>
的 DEMO 强>
答案 1 :(得分:0)
我实际上找到了比@ charlietfl更好的解决方案(对于我的用例):在闭包中缓存过滤器级别的随机结果,并在摘要期间将其返回给随机结果。当我需要一个新的随机值时,我就可以破解缓存,无论如何我在$ interval中做了。
我告诉他“接受的回答”标志,因为他解释了为什么,而不仅仅是如何。