AngularJS 1.2 中的 random orderBy 返回“infdig”错误

IT技术 javascript angularjs angularjs-orderby
2021-03-01 15:06:46

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"]]

的文档orderBy没有使用函数表达式的示例,只有字符串表达式。有什么改变,还是这是一个错误?

2个回答

我不确定以前的版本,但在当前版本中,在作用域上观察的任何表达式,例如传递给的表达式,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.
2021-05-01 15:06:46
我通过rank为现有数组中的每个项目添加一个值而不是创建一个新的“排名”数组来简化此操作谢谢你的主意,
2021-05-20 15:06:46

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

如果你愿意,你可以用你自己的算法代替洗牌的内容。

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

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

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

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

您可以替换 lodash。
2021-04-29 15:06:46
嗨@DavidAnderton 我想表明进行洗牌的正确位置是在过滤器中。过滤器应该用于处理数据。在我看来,实现 shuffle 的实际机制是 JavaScript 问题,超出了它的范围。
2021-05-02 15:06:46
如果您愿意,您可以编写自己的 shuffle 函数,但由于 shuffle 是一个已解决的问题,我认为这是使用库的好时机。
2021-05-03 15:06:46
我没有使用下划线。
2021-05-06 15:06:46
我投了反对票,因为我觉得该解决方案应该可以在没有任何外部库的情况下实现,并且包括仅用于单个随机化的库是矫枉过正的。经过反思,这不是实际问题的一部分,而是与我面临的问题更相关。如果您在此处进行任何编辑评论,我将通过赞成票取消我的反对票。
2021-05-09 15:06:46