Knockout Performance - Filtering an Observable Array

筅森魡賤 提交于 2020-01-16 00:59:13

问题


I'm new to Knockout, and I'm trying to use it on a page showing a system's users and the roles that each user has.

The data is in an observableArray of users. The user object has a roles property, which is another observableArray. This second array contains an object for each role, with an ID and a boolean "granted" property.

I want to be able to display all of the users with a specific role, so there's a checkbox for each role - when one of these is checked, the list should show the users with that role.

The problem I've got is that filtering the 1,000 or so users by roles takes several seconds. Filtering by the text in the name is very quick (a few milliseconds), but filtering by role is not. I've put some timing code in, and the issue is the method I'm using to check whether the user has the selected role(s) so I'm just wondering whether there's a better way of doing it, maybe using some Knockout magic.

Below is the ko.computed on the view model that I'm using to do the filtering. The results table is bound to this function.

self.filteredUsers = ko.computed(function () {

    var textFilter = self.filter();          // this is an observable bound to a text field
    var checkedRoles = self.selectedRoles(); // this is a computed, which returns an array of checked roles

    return ko.utils.arrayFilter(self.users(), function (user) {

        var match = true;

        if (user.displayName.toLowerCase().indexOf(textFilter.toLowerCase()) == -1) {
            match = false;
        }

        // for each ticked role, check the user has the role
        for (var i = 0; i < checkedRoles.length; i++) {
            var roleMatch = false;
            for (var j = 0; j < user.roles().length; j++) {
                if (user.roles()[j].roleId === checkedRoles[i].roleId && user.roles()[j].granted()) {
                    roleMatch = true;
                    break;
                }
            }
            if (!roleMatch) {
                match = false;
            }
        }

        return match;
    });
});

回答1:


I think that a good optimization would be creating a grantedRoles computed on your user object. This computed would return an object that you can use as an index, would contain properties keyed by a role's unique identifier and would only contain roles that are granted.

Then in filteredUsers, you would check the grantedRoles object against each checked role, rather than looping through user.roles() for each checked role.



来源:https://stackoverflow.com/questions/13880015/knockout-performance-filtering-an-observable-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!