如何在没有无限循环消化随机创建/洗牌过滤器 [英] How to create random/shuffle filter without infinite digest loop

查看:220
本文介绍了如何在没有无限循环消化随机创建/洗牌过滤器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要实现以下目标:


  • 要能够在随机顺序排列显示图片。

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

To solve this, I decided to create a 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;
        }
    }

现在在模板,我打电话为:

Now in template, I am calling as:

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

不过,我得到这个错误:

However, I am getting this error:

未捕获的错误:[NG-模块化错误] [$ rootScope:infdig] 10 $摘要()
  迭代到达。中止!观察家在过去的5次迭代解雇:
  [[{味精:FN:
  前pressionInputsWatch,的newval:的http://本地主机:3002 /文档/视图/ 158 ,OLDVAL:的http://本地主机:3002 /文档/视图/ 159 },{味精:FN:

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:

做了一些研究之后,我发现这是做价值的变化,但如果我改变我的价值观。

After doing some research, I found that it is do with value changes, but where I am changing my values.

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

Now I can understand that some how it might be the scope is changing. However, what I have noticed that even if I have a simple filter like this: {{p.documents | console}}

和控制台过滤器只需要在控制台中的数组和打印。

and the console filter just takes an array and print in the console.

现在,当我在列表中10个对象,它是调用过滤器的30倍。

Now when I have 10 objects in the list, It is calling filter 30 times.

下面是控制台过滤器是如何,​​但对于10个项目被调用66次。

Here is how the console filter is, but for 10 items it is calling 66 times.

为什么?

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);
            }
        }
    };

我在这里甚至没有返回不同的值。(如果我的逻辑去解释在这里 - 的角:无限消化过滤循环)

即使它不是一个过滤器,然后也它引起此问题

Even if it is not a filter,then also it is causing this problem

现在,我已经创建了一个服务功能,和我有这个问题。

Now that I have created a service function, and I am having this problem.

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


vm.random = function (a, s) {

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

那么该如何解决?

So what is the solution??

推荐答案

要修复无限摘要,你需要用你的过滤器在 memoize的功能。为您解决问题的最好办法是从安装克努特洗牌 lodash NPM ,然后用你喜欢的模块系统来创建过滤器。这个例子是CommonJS的/ browserify。

To fix the infinite digest, you need to wrap your filter in a memoize function. The best way to solve your problem is to install knuth-shuffle and lodash from npm, then use whatever module system you like to create the filter. This example is with CommonJS/browserify.

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

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

在创建过滤器这种方式,你可以当空值传递给随机功能有问题。在这种情况下,只需添加一个检查:

When creating filters this way, you may have a problem if an empty value is passed to the shuffle function. In that case, just add a check:

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

您可以了解更多关于 这个答案 无限的消化问题。

You can learn more about the infinite digest problem from this answer.

要重新洗牌的列表,你可以任意的$ scope属性传递给过滤器,然后当你要重新洗牌改变这种属性。无论是递增的数字或使用的Math.random()是做到这一点的好办法。这工作,因为结果是根据传递的参数缓存,所以传递一个无用的,否则参数产生一个新的结果。

To re-shuffle the list, you can pass an arbitrary $scope property to the filter, then change that property when you want to re-shuffle. Either incrementing a number or using Math.random() are a good way to do this. This works because the result is cached according to the arguments passed, so passing an otherwise useless argument produces a new result.

myList | shuffle:whatever

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

这篇关于如何在没有无限循环消化随机创建/洗牌过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆