Custom filter vs filter function in controller performance comparison
Suppose I have an array of 5000 objects (with boolean values) which I have to ng-repeat
in the template:
$scope.arr = [
{
"value": true
},
{
"value": false
},
{
"value": false
}
//and so on
]
Now, I want to filter this ng-repeated
array on the basis of a dynamic variable, say 'show_filter', which I am setting elsewhere.
If 'show_filter' is set to 'all' I want to show all the objects. If it is set to false (the boolean value) then I want to show objects with 'value' key set to false. Same goes for when 'show_filter' is set to true.
So, there are two approaches:
1. Build a custom filter:
I would write a custom filter for the filtering task like this:
filter:
app.filter('filterArr', function() {
return function(arr, show_filter) {
var filtered_arr = [];
if(show_filter != 'All') { //if show_filter is a boolean value
for(var i = 0; i < arr.length; i++) {
if(arr[i].value == show_filter) {
filtered_arr.push(arr[i]);
}
}
return filtered_arr;
}
else {
return arr; //return the entire array if show_filter is set to 'All'
}
}
})
template:
obj in arr | filterArr : show_filter
2. Write a filter function in the controller:
filter:
$scope.filterObjects = function(arr) {
var filtered_arr = [];
if($scope.show_filter != 'All') { //if $scope.show_filter is a boolean value
for(var i = 0; i < arr.length; i++) {
if(arr[i].value == $scope.show_filter) {
filtered_arr.push(arr[i]);
}
}
return filtered_arr;
}
else {
return arr; //return the entire array if show_filter is set to 'All'
}
}
template:
obj in filterObjects(arr)
Which of the above two methods will be faster? I have seen the custom filter code execute everytime for each digest loop and not only for changes made to $scope.show_filter
, which leds me to believe its quite inefficient. Although I am not sure which is faster between the two ways.
Both functions will be called in every digest cycle. That's somewhat obvious for the second function. The return value of filterObjects(arr)
could be different on every call.
It's not so obvious why a filter would be called in every digest cycle. The documentation states the following:
The filter function should be a pure function, which means that it should be stateless and idempotent. Angular relies on these properties and executes the filter only when the inputs to the function change.
So if neither arr
nor show_filter
change then the filter shouldn't be called, right? But here's the catch: Detecting a change in arr
is costly.
Angular has to make a copy of the array to compare it with the current content. Even if nothing has changed, every single item has to be compared. And if the items are objects every single property of them has to be compared. Directly calling a filter instead is much cheaper. And that's what Angular does when a filter is applied to an array (or object).
To speed up the application you have two choices. The first one is to filter the array only when it's necessary and to expose the filtered array to ng-repeat
. Eg if you can enter a value by which the array will be filtered, then filter the array whenever that value changes.
The second alternative can be used if both the array and the filter don't change (so not in your case). Then you can use one-time binding:
<li ng-repeat="item in ::array | filter">
That's useful when you have a fixed set of items and want to sort them by name eg The filter will be called only once in that case.
链接地址: http://www.djcxy.com/p/88954.html上一篇: 如何观察java rx中的调用线程?
下一篇: 自定义过滤器与控制器性能比较中的过滤功能