如何在没有无限循环消化随机创建/洗牌过滤器 [英] How to create random/shuffle filter without infinite digest loop
问题描述
我要实现以下目标:
- 要能够在随机顺序排列显示图片。
要解决这个问题,我决定创建一个过滤器:
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的
功能。为您解决问题的最好办法是从安装
,然后用你喜欢的模块系统来创建过滤器。这个例子是CommonJS的/ browserify。克努特洗牌
和 lodash
NPM
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屋!