如何创建没有无限摘要循环的随机/随机过滤器 [英] How to create random/shuffle filter without infinite digest loop

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

问题描述

我想实现以下目标:

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

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

var app = angular.module('app');应用程序.过滤器('随机化器',随机化器);函数随机发生器(){返回函数(集合,默认值){var 结果 = 默认值;如果(!!集合){if (Array.isArray(collection) && collection.length === 1) {结果 = 集合[0] ||默认值;} else if (!Array.isArray(collection)) {结果 = 集合 ||默认值;} 别的 {//请在此处随机化var idx = parseInt(((Math.random()) * collection.length));结果 = 集合[idx] ||默认值;}}返回结果;}}

现在在模板中,我调用:

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

但是,我收到此错误:

<块引用>

未捕获的错误:[NG-Modular Error] [$rootScope:infdig] 10 $digest()迭代达到.中止!观察者在最近 5 次迭代中被触发:[[{"msg":"fn:expressionInputsWatch","newVal":"http://localhost:3002/documents/view/158","oldVal":"http://localhost:3002/documents/view/159"},{"msg":"fn:

在做了一些研究之后,我发现它与价值变化有关,但我正在改变我的价值.

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

并且控制台过滤器只需要一个数组并在控制台中打印.

现在当列表中有 10 个对象时,它会调用 filter 30 次.

控制台过滤器是这样的,但对于 10 个项目,它调用了 66 次.

为什么??

app.filter('console', pipeConsole);功能管道控制台(){返回函数(值,o){打印(值);打印(o);打印(计数);}功能打印(o){如果 (!!o) {控制台日志(o);}否则如果(o === null){控制台警告(o);}}};

在这里我什至没有返回不同的值......(如果我遵循这里解释的逻辑 - Angular:过滤器中的无限摘要循环)

即使不是过滤器,也是造成这个问题的原因

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

 <img ng-src="{{vm.baseUrl + 'documents/view/' + vm.random( p.documents , {id: 'notfound'}).id }}">vm.random = 函数 (a, s) {返回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() {返回记忆(随机播放);});

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

app.filter('shuffle', function() {返回记忆(功能(输入){如果(输入 === 未定义){ 返回;}返回 shuffle.apply(null, arguments);});});

您可以从这个答案中了解有关无限摘要问题的更多信息.

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

myList |洗牌:随便

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

I would want to achieve the following:

  • To be able to show image from array in random order.

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:

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.

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.

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

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

Why ??

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

Here I am not even returning different values... (if I go with the logic explained here - Angular: infinite digest loop in filter)

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

解决方案

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.

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天全站免登陆