javascript - 如何创建没有无限摘要循环的随机/随机过滤器

标签 javascript angularjs angularjs-filter

我希望实现以下目标:

  • 能够以随机顺序显示数组中的图像。

为了解决这个问题,我决定创建一个过滤器:

var app = angular.module('app');
app. filter('randomizer', randomizer);


 function randomizer() {

        return function (collection, defaultValue) {

            var result = defaultValue;

            if (!!collection) {
                if (Array.isArray(collection) && collection.length === 1) {
                    result = collection[0] || defaultValue;
                } else if (!Array.isArray(collection)) {
                    result = collection || defaultValue;
                } else {
                    // randomize here please
                    var idx = parseInt(((Math.random()) * collection.length));
                    result = collection[idx] || defaultValue;
                }
            }

            return result;
        }
    }

现在在模板中,我调用为:

<div class="masonry-pin masonry-brick" ng-repeat="p in vm.list | orderBy: 'updatedAt':true">

     <img ng-src="{{vm.baseUrl + 'documents/view/' + ( p.documents | randomizer:{id: 'notfound'}:p.id).id }}">

</div>

但是,我收到此错误:

Uncaught Error: [NG-Modular Error] [$rootScope:infdig] 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations: [[{"msg":"fn: expressionInputsWatch","newVal":"http://localhost:3002/documents/view/158","oldVal":"http://localhost:3002/documents/view/159"},{"msg":"fn:

经过一些研究,我发现这与值(value)观的变化有关,但我正在改变我的值(value)观。

现在我可以理解范围可能正在发生变化。然而,我注意到,即使我有一个像这样的简单过滤器:{{p.documents |控制台}}

控制台过滤器只接受一个数组并在控制台中打印。

现在,当我的列表中有 10 个对象时,它会调用过滤器 30 次。

以下是控制台过滤器的结构,但对于 10 个项目,它调用了 66 次。

为什么?

app.filter('console', pipeConsole);

function pipeConsole() {


        return function (value, o) {
            print(value);
            print(o);
            print(count);

        }

        function print(o) {
            if (!!o) {
                console.log(o);
            }
            else if (o === null) {
                console.warn(o);
            }
        }
    };

这里我什至没有返回不同的值...(如果我按照此处解释的逻辑 - Angular: infinite digest loop in filter )

即使它不是过滤器,也会导致此问题

现在我已经创建了一个服务函数,但我遇到了这个问题。

 <img ng-src="{{vm.baseUrl + 'documents/view/' + vm.random( p.documents , {id: 'notfound'}).id }}">


vm.random = function (a, s) {

            return utility.randomizer(a, s);
        };

那么解决办法是什么?

最佳答案

要修复无限摘要,您需要将过滤器包装在 memoize 函数中。解决问题的最佳方法是从 npm 安装 knuth-shufflelodash,然后使用您喜欢的任何模块系统来创建过滤器。此示例使用 CommonJS/browserify。

var memoize = require('lodash/function/memoize');
var shuffle = require('knuth-shuffle');

app.filter('shuffle', function() {
  return memoize(shuffle);
});

以这种方式创建过滤器时,如果将空值传递给 shuffle 函数,则可能会出现问题。在这种情况下,只需添加一个检查:

app.filter('shuffle', function() {
  return memoize(function(input) {
    if (input === undefined) { return; }
    return shuffle.apply(null, arguments);
  });
});

您可以从this answer了解有关无限摘要问题的更多信息。 .

要重新洗牌列表,您可以将任意 $scope 属性传递给过滤器,然后在想要重新洗牌时更改该属性。递增数字或使用 Math.random() 是实现此目的的好方法。这是可行的,因为结果是根据传递的参数进行缓存的,因此传递一个无用的参数会产生一个新的结果。

myList | shuffle:whatever
$scope.whatever = 0;
$scope.reshuffle = function() {
  ++$scope.whatever;
  // OR
  $scope.whatever = Math.random();
};

关于javascript - 如何创建没有无限摘要循环的随机/随机过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30435382/

相关文章:

javascript - JavaScript 中的 DigestUtils sha256 编码等效项是什么?

angularjs - 全局 $sce.trustAsResourceUrl()

javascript - Django 客户端过滤

javascript - Angularjs groupBy + orderBy

javascript - AngularJS 中使用整数字段进行过滤

javascript - AngularJS - 如何在嵌套 ng-repeat 中对过滤的孙项目求和

javascript - Vuex 存储状态不更新屏幕/Vue-Native

javascript - JavaScript 数组中的对象插入问题

javascript - 如何在用户单击内部时自动展开 DIV 元素中的 IFrame?

angularjs - Angular 剑道下拉