【问题标题】:random orderBy in AngularJS 1.2 returns 'infdig' errorsAngularJS 1.2 中的随机 orderBy 返回“infdig”错误
【发布时间】:2014-02-05 19:12:37
【问题描述】:

this question 中使用随机的orderBy 排序技术在AngularJS 1.1 中可以正常工作。

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
    $scope.list = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
    $scope.random = function() {
        return 0.5 - Math.random();
    }
}

不过,在 1.2 中,它会将 infdig 错误放入控制台,并且需要更长的时间才能返回排序结果:http://jsfiddle.net/mblase75/jVs27/

控制台中的错误如下:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["fn: $watchCollectionWatch; newVal: 42; oldVal: 36"],["fn: $watchCollectionWatch; newVal: 47; oldVal: 42"],["fn: $watchCollectionWatch; newVal: 54; oldVal: 47"],["fn: $watchCollectionWatch; newVal: 61; oldVal: 54"],["fn: $watchCollectionWatch; newVal: 68; oldVal: 61"]]

The documentation for orderBy 没有使用函数表达式的示例,只有字符串表达式。有什么变化吗,或者这是一个错误?

【问题讨论】:

标签: javascript angularjs angularjs-orderby


【解决方案1】:

我不确定以前的版本,但在当前版本中,在作用域上观察的任何表达式,例如传递给 ng-repeat 的表达式,通常每个摘要至少评估两次。仅当整个 Angular 应用程序的所有范围内的所有评估表达式的结果在两次连续评估之间都相同时,摘要循环才会结束。

因为每次评价

<li ng-repeat="i in list | orderBy:random">{{i}}</li>

导致调用 random(),因此顺序不同,然后 Angular 将继续评估表达式,直到达到 10 次摘要迭代的限制,并引发错误。

解决方案是在模板之外的控制器中设置顺序:

$scope.list = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
$scope.rankedList = [];
angular.forEach($scope.list, function(item) {
    $scope.rankedList.push({
        item: item,
        rank: 0.5 - $window.Math.random()
    });
});

然后通过以下方式使用该字段进行排序:

<li ng-repeat="i in rankedList | orderBy:'rank'">{{i.item}}</li>

这可以在jsfiddle 看到。

【讨论】:

  • 好答案——我更进一步,将“随机等级”生成器放在一个作用域函数中,这样我就可以通过ng-click在我的应用程序中按需触发它。
  • 我通过为现有数组中的每个项目添加一个rank 值而不是创建一个新的“排名”数组来简化这一点。感谢您的想法,
【解决方案2】:

您可以使用简单的自定义过滤器以 Angular 的方式解决此问题。在这里,我使用了实现 Fischer-Yates 的下划线 shuffle 方法。

如果您愿意,可以用自己的算法替换随机播放的内容。

angular.module('shuffle', [])
  .filter('shuffle', function() {
    return function(ary) {
      return _.shuffle(ary);
    }
  });

我们现在可以通过这个过滤器来管道我们的数组,就像这样:

<li ng-repeat='option in options | shuffle'>

过滤器将在模板渲染时调用一次。

【讨论】:

  • 我没有使用下划线。
  • 你可以用lodash代替。
  • 如果您愿意,可以编写自己的 shuffle 函数,但由于 shuffle 是一个已解决的问题,我认为这是使用库的好时机。
  • 我投了反对票,因为我觉得解决方案应该在没有任何外部库的情况下是可行的,并且只包含一个用于单个随机化的库是矫枉过正的。经过反思,这不是实际问题的一部分,而是与我面临的问题更相关。如果您在此处进行任何编辑评论,我会用赞成票取消我的反对票。
  • 嗨@DavidAnderton 我想表明进行随机播放的正确位置是在过滤器中。过滤器应该用于处理数据。在我看来,实现 shuffle 的实际机制似乎是 JavaScript 问题,超出了它的范围。
猜你喜欢
  • 2020-08-28
  • 1970-01-01
  • 2013-04-13
  • 2016-10-27
  • 2020-12-23
  • 1970-01-01
  • 2014-08-12
  • 2013-10-21
  • 1970-01-01
相关资源
最近更新 更多