11

我的角度代码中出现以下错误。我很难理解为什么函数 getDrawWithResults 会导致摘要循环,因为似乎没有任何副作用?它只是从列表中返回属性设置为 true 的项目。

该错误仅在页面上首次使用 getDrawWithResults 时发生,如果我删除,则错误停止。

Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["getDrawsWithResults(selectedLottery.draws); newVal: []; oldVal: []"],["getDrawsWithResults(selectedLottery.draws); newVal: []; oldVal: []"],["getDrawsWithResults(selectedLottery.draws); newVal: []; oldVal: []"],["getDrawsWithResults(selectedLottery.draws); newVal: []; oldVal: []"],["getDrawsWithResults(selectedLottery.draws); newVal: []; oldVal: []"]]

这是我的代码:

HTML

<h4 ng-cloak ng-hide="getDrawsWithResults(selectedLottery.draws)">Results of Selected Lottery</h4>

<div class="con" ng-repeat="draw in getDrawsWithResults(selectedLottery.draws)" ng-cloak>
    <h5 class="con__header">[[ draw.date|date:'EEEE d MMMM yyyy - H:mm' ]]</h5>
    <div class="balls-list__outer con__row">
        <div class="balls-list">
            <div class="balls-list__ball__outer" ng-repeat="b in draw.results">
                <button class="balls-list__ball btn btn-con">[[ b ]]</button>
            </div>

        </div>
    </div>
</div>

JS

// return list of draws with results
$scope.getDrawsWithResults = function(draws) {
    return _.filter(draws, function(draw){
        return draw.results && draw.results.length > 0;
    });
}
4

2 回答 2

14

我假设_.filter每次运行时都会返回一个新的数组实例。这会导致 Angular 的隐式$watches 像:

ng-hide="getDrawsWithResults(selectedLottery.draws)"

ng-repeat="draw in getDrawsWithResults(selectedLottery.draws)"

认为模型已经改变,所以它需要再次消化。

我会实现一个过滤器

app.filter('withResults', function() {
    return function(draws) {
        return _.filter(draws, function(draw){
            return draw.results && draw.results.length > 0;
        });
    }
})

并像这样应用它(见下面的编辑):

ng-hide="selectedLottery.draws | withResults"

ng-repeat="draw in selectedLottery.draws | withresults"

在评论中讨论后编辑

实际问题是这个绑定:

ng-hide="getDrawsWithResults(selectedLottery.draws)"

ng-hide注册一个将永远触发的手表,因为过滤数组的引用总是改变。可以改为:

ng-hide="getDrawsWithResults(selectedLottery.draws).length > 0"

和相应的过滤器:

ng-hide="(selectedLottery.draws | withResults).length > 0"

ng-repeat没有同样的问题,因为它注册了一个$watchCollection.

于 2013-11-08T17:12:10.383 回答
7

这意味着$scope.getDrawsWithResults()不是幂等的。给定相同的输入和状态,它不会始终返回相同的结果。并且ng-hide需要一个幂等函数(就像 Angular 所关注的所有函数一样)。

简而言之,使用返回单个布尔结果而不是_.filter返回数组的函数可能会更好。也许_.all

幂等性之所以重要,是因为 Angular 的 $digest 循环的工作方式。由于您的ng-hideAngular 对您的$scope.getDrawsWithResults(). 这样,每当它应该重新评估它时,它就可以收到警报ng-hide。你ng-repeat不会受到影响,因为它的结果不需要被 Angular 监视。

因此,每次发生 $digest (每秒多次)时$scope.getDrawsWithResults(),都会调用它来查看它的结果是否与前一个 $digest 循环相比发生了变化,从而它是否应该改变ng-hide。如果结果发生了变化,Angular 知道这也可能意味着它正在监视的其他一些函数(可能使用你函数的结果)可能已经发生了变化。因此它需要重新运行 $digest (如果需要,让更改通过系统传播)。

所以 $digest 会一直运行,直到它观察到的所有函数的结果都停止变化。或者直到有 10 个 $digest 循环。Angular 假设如果系统在 10 个周期后不稳定,它可能永远不会稳定。所以它放弃并抛出你得到的错误信息。

如果您愿意,可以在这里更深入地了解这一切:http: //teropa.info/blog/2013/11/03/make-your-own-angular-part-1-scopes-and-digest。 html

于 2013-11-08T17:02:01.203 回答