如何使用Firebase / AngularFire从非规范化数据集加载(n> 2)级嵌套数据?

时间:2014-05-07 18:16:06

标签: angularjs firebase angularfire

给定非规范化数据结构,如:

{
  "users" : {
    "-JMMXslDJkPYmgcwXUzP" : {
      "items" : [ "-JMMXYaWlg_ftL2sKsdp", ... ],
      "name" : "user0"
    },
    ...
  },
  "items" : {
    "-JMMXYac7EMZcr4LIL5u" : {
      "properties" : [ "-JMMWdpWig-L8oIqbeI1", ... ],
      "name" : "item0"
    },
    ...
  },
  "properties" : {
    "-JMMWdpe3WEyjnUM12o2" : {"name": "property0"},
    ...
  }
}

我目前正在加载嵌套子项,如下所示:

<ul ng-init="users = $ref('users')">
    <li ng-repeat="user in users">
        <h1>{{ user.name }}</h1>
        <ul>
            <li ng-repeat="item_id in user.items" ng-init="item = $ref('items/'+item_id)">
                <h2>{{ item.name }}</h2>
                <ul>
                    <li ng-repeat="property_id in item.properties" ng-init="property = $ref('properties/'+property_id)">
                        <h3>{{ property.name}}</h3>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

这里的搜索者显示了只有3级深度嵌套数据,加载速度难以承受的速度如何:http://plnkr.co/edit/yrRx2FYJEc5BM1MaSQDe?p=preview

如何加快加载/呈现此数据的速度?

  • 请注意,发布here的解决方案(为每个集合创建一个引用而不是每个集合项)对我来说不起作用,因为我的任何/所有嵌套集合都太大了。

1 个答案:

答案 0 :(得分:4)

这里的问题是编译器。每当这些记录中的任何一个发生变化时,所有这些ng-repeat操作都将被重新运行,并且数据会一次又一次地被下载。而是使用项目缓存。

由于我已经写过an example of a user cache previously,我只是从中借用并转出变量以匹配您的示例。您需要调整它以使用属于每个用户的多个项目;请原谅我这种懒惰:

观点:

<li ng-repeat="user in users" ng-init="item = items.$load(user.item_id)">
    {{user.name}}: {{item.name}}
</li>

控制器:

// CONTROLLER

app.controller('ctrl', function ($scope, $firebase, itemCache) {
    $scope.users = $firebase(fb.child('users'));
    $scope.items = itemCache(fb.child('items'));
    $scope.$on('$destroy', $scope.items.$dispose);
});

app.factory('itemCache', function ($firebase) {
    return function (ref) {
        var cachedItems = {};
        cachedItems.$load = function (id) {
            if( !cachedItems.hasOwnProperty(id) ) {
                cachedItems[id] = $firebase(ref.child(id));
            }
            return cachedItems[id];
        };
        cachedItems.$dispose = function () {
            angular.forEach(cachedItems, function (item) {
                item.$off();
            });
        };
        return cachedItems;
    }
});