在AngularJS中聚合对象

时间:2015-11-17 07:57:17

标签: javascript json angularjs

所以,我正在尝试使用AngularJS,并且,作为练习,我想我会使用Steam API创建一个简单的应用程序。我做了一个简单的Spring Boot Rest服务,它为Steam API提供反向代理服务,以便可以转发某些调用。此时有两个动作:

/user/提供了蒸汽ID列表。 /user/:id/games提供以下api的输出: http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=MY_STEAM_KEY&steamid=STEAM_ID&format=json

以下列格式返回答案:

{  
   "response":{  
      "game_count":3,
      "games":[  
         {  
            "appid":70000,
            "playtime_forever":0
         },
         {  
            "appid":550,
            "playtime_forever":0
         },
         {  
            "appid":274900,
            "playtime_forever":0
         }
      ]
   }
}

我想要实现的是从这个json对象中提取games数组,并将其附加到正确的用户。我想为所有用户这样做。通过定义以下工厂,我已经使用$ resource对象实现了我想要的东西:

angular.module("SAM.Resources", [])
    .factory("UserList", ["$resource",
        function ($resource) {
            return $resource('/user');
        }])

    .factory("GamesList", ["$resource",
        function ($resource) {
            return $resource('/user/:id/games', {
                id: '@id'
            });
        }
    ]);

然后在我的控制器中使用以下内容:

UserList.query(function(response){
    $scope.users = response ? response : [];
    for(index=0; index < $scope.users.length; ++index){
        user = $scope.users[index];
        $scope.users[index].games = GamesList.get({id:user.id});
    }
});

这接近我想要的,然而,它会返回以下格式:

  {
    "id": "76561198119953061",
    "name": "Yuri",
    "games": {
      "response": {
        "game_count": 3,
        "games": [
          {
            "appid": 70000,
            "playtime_forever": 0
          },
          {
            "appid": 550,
            "playtime_forever": 0
          },
          {
            "appid": 274900,
            "playtime_forever": 0
          }
        ]
      }
    }
  }

我不想要games.response.games构造。我试图将其改为:

$scope.users[index].games = GamesList.get({id:user.id}).response.games;
失败的

似乎是合乎逻辑的,因为它是一个承诺,并且不会立即包含响应对象。

我也尝试使用像

这样的东西
GamesList.get({id:user.id}), function(response){
 angular.extend(user, response);
});

确实将响应附加到user对象,只有user对象始终是promise解析时数组中的最后一个值。

所以基本上我的问题归结为:如何使用User列表扩展我的Games对象?

2 个答案:

答案 0 :(得分:2)

您需要稍微改变一下代码:

UserList.query(function(response){
    $scope.users = response ? response : [];
    for(index=0; index < $scope.users.length; ++index){
        user = $scope.users[index];

        (function(index, id){
            GamesList.get({id: id}, function(response){ // Get the games from the response
                $scope.users[index].games = response.response.games;
            }));
        })(index, user.id)
    }
});

for循环中,user不断更改值。当第一个GameList.get返回一个值时,您的循环将在最后一个用户处。

IIFE包裹在一个单独的范围内将这些变量分开。

答案 1 :(得分:1)

for(index=0; index < $scope.users.length; ++index){
    user = $scope.users[index];
    $scope.users[index].games = GamesList.get({id:user.id}, function(response){
        angular.extend(user, response);
    }));
}

当您这样做时,用户变量将在每一步都改变。但匿名回调将在稍后执行。所以只使用了最后一个用户。

您可以使用匿名函数作为forEach的范围:

来解决此问题
$scope.users.forEach(function(user) {
    $scope.users[index].games = GamesList.get({id:user.id}, function(response){
        angular.extend(user, response);
    }));
});

如果您想避开user.games.response.games,则需要以不同的方式合并对象。

$scope.users.forEach(function(user) {
    $scope.users[index].games = GamesList.get({id:user.id}, function(response){
        user.games = response.games;
        user.games_count = response.games_count;
    }));
});