自定义过滤器与控制器性能比较中的过滤功能 [英] Custom filter vs filter function in controller performance comparison

查看:215
本文介绍了自定义过滤器与控制器性能比较中的过滤功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个5000个对象(带有布尔值)的数组,我必须在模板中使用 ng-repeat

  $ scope.arr = [
{
value:true
},
{
值:false
},
{
value:false
}
//等等
]


$ b现在,我想根据一个动态变量,比如说'show_filter',我正在设置其他地方。



如果'show_filter'设置为'all',我想显示所有的对象。如果它设置为false(布尔值),那么我想显示对象的值键设置为false。当'show_filter'被设置为true时也是如此。

所以有两种方法:

强> 1。构建一个自定义过滤器:



我会为过滤任务编写自定义过滤器,如下所示:



filter:

  app.filter('filterArr',function(){$ b $如果(show_filter!='All'){// show_filter是一个布尔值
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; //如果show_filter设置为'All',则返回整个数组

}
})

template:

  obj in arr | filterArr:show_filter 

2。在控制器中写入一个过滤器函数:

过滤器:

  $ scope.filterObjects = function(arr){
var filtered_arr = [];
if($ scope.show_filter!='All'){//如果$ scope.show_filter是一个布尔值
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;如果show_filter设置为'All'
}
}



,则返回整个数组

  obj in filterObjects(arr)

以上两种方法中的哪一种会更快?我已经看到了每个摘要的自定义过滤代码循环,而不仅仅是对 $ scope.show_filter 所作的修改,这使我相信它效率很低。虽然我不确定两种方法之间哪个更快。

解决方案

这两个函数都将在每个摘要循环中调用。这对于第二个功能来说是显而易见的。 filterObjects(arr)的返回值在每个调用中都可能不同。



为什么 filter 将在每个摘要循环中调用。该文档声明如下:

lockquote

过滤函数应该是一个纯函数,这意味着它应该是无状态和幂等的。 Angular依赖于这些属性,只有当函数的输入发生变化时才执行过滤器。

所以如果 arr 也不是 show_filter 改变那么过滤器不应该被调用,对吧?但是这里有一个问题:在 arr 中检测到一个变化是非常昂贵的。

Angular必须复制数组将其与当前内容进行比较。即使没有任何变化,每一个项目都必须进行比较。如果这些物品是物品的每一个属性都必须进行比较。直接调用一个过滤器,而不是更便宜。这就是当一个过滤器应用到数组(或对象)时Angular所做的事情。



为了加速应用程序,您有两个选择。第一个是只在必要时过滤数组,并将过滤的数组展示给 ng-repeat 。例如。如果您可以输入一个数组,该数组将被过滤,然后过滤该数组,只要该值发生变化。

如果数组和过滤器都没有改变,那么可以使用第二种方法。然后你可以使用一次绑定:

 < li ng-repeat =item in :: array | filter> ; 

当您有一组固定的项目并想按名称排序时,在这种情况下,过滤器只会被调用一次。


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 arrnor 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. E.g. 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 e.g. The filter will be called only once in that case.

这篇关于自定义过滤器与控制器性能比较中的过滤功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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