2014-07-17 35 views
0

我在AngularJS的世界新的,和我面临着一个有趣的问题:交换数据AngularJS电话

我创建了一个角厂家服务,作为服务代理工作的REST我正在调用服务。 我的服务代理看起来像这样:

angular.module('myApp').factory('myService', ['$http', function($http) { 

    var baseAddr = "http://myservice.com"; 
    var token = "secure_identifier"; 

    var MyService = { 
     doRequest: function(method, path, token, postData) { 
      return $http({method: method, url: baseAddr+path, headers: {....}, data:postData }); 
     } 
    } 

    return { 

     GetGroupUsers: function(id) 
     { 
      return MyService.doRequest('GET', '/api/groupusers/'+id+'.json', token, null); 
     }, 
     GetUser: function(id) 
     { 
      return MyService.doRequest('GET', '/api/users/'+id+'.json', token, null); 
     } 
    } 
}]); 

所以GetGroupUsers返回用户ID-S属于给定的组中,和的getUser返回 指定成员的属性(例如电子邮件地址的阵列,全名,用户名,出生日期)。 我想要的是查询一个组(获取该组中的userid-s),并在GetUser(userid)方法的帮助下将用户的名称附加到数组项 。 我有一个控制器,其中我通过我的代理服务来查询这个服务。这里是控制器的相关部分:

//... 
MyService.GetGroupUsers(GroupId).then(function(userlist) 
{ 
    //userlist is an array of a complex object that consists of userId-s and groupId-s 
    //Suppose that it looks like this: 
    // [ {uid: 1, groupId: 1}, {uid: 2, groupId: 1}, {uid: 3, groupId: 1},...,.. ] 
    $scope.groups = userlist.data; 

    //but i need to attach for every item in the array the name of the selected user 
    // [ {uid: 1, groupId: 1,username: 'Alga Rithem'}, {uid: 2, groupId: 1, username:'Anna Nimmity'}, {uid: 3, groupId: 1, username:'Anna Conda'},...,.. ] 

    //So I iterate over the userlist 
    for (var i = 0; i < userlist.data.length; i++) 
    { 
     MyService.GetUser(userlist.data[i].uid). 
      then(function(user) 
      { 
       //And here is the problem I'm facing with: 
       //The value of variable "i" becomes obsolate, because GetUser call is async to the for-loop 
       // when the "then" "callback" executes, the loop may has been finished already! 
       //So I dont really know, where to put the value I've just received 
       //I need that value of i, what it was when i called the service!    
       $scope.groups[i].name = user.data.name; //So this is WRONG! 
      }); 
    } 
}); 

//... 

我解决了这个问题,一个小黑客: 我延长了的getUser(用户名)与一个参数的PARAMETERLIST到的getUser(用户名,标签)。在这个标签中,我可以把任何我想要 检索回调。

所以我修改我的代码一点点:

修改控制器代码:

//... 

MyService.GetGroupUsers(GroupId).then(function(userlist) 
{  
    $scope.groups = userlist.data; 

    for (var i = 0; i < userlist.data.length; i++) 
    { 
     MyService.GetUser(adat.data[i].uid). 
      then(function(user) 
      {     
       $scope.groups[parseInt(user.config.tag)].name = user.data.name; //This Works fine! 
      }); 
    } 
}); 

//Service proxy 

doRequest: function(method, path, token, postData,tag) { 
      return $http({method: method, url: baseAddr+path, headers: {....}, data:postData }); 
     } 
//... 

GetUser: function(id, tag) 
     { 
      return MyService.doRequest('GET', '/api/users/'+id+'.json', token, null,tag); 
     } 

现在我可以在我的控制器检索我有效的,过去值我的问题是:这个解决方案在技术上是否正确?这样的问题的最佳做法是什么? AngularJS有这个工具吗?

ps:修改REST服务API以返回用户名也不是这种情况下的解决方案。

在此先感谢

+0

如果你的API很安静,可以考虑使用'$ resource',这使得事情变得更容易。另外,你可以显示所有信息'GetUser'完全返回吗? – Pak

+0

让我们假设GetUser返回一个像这样的JSON对象: “{ ”id“:9, ”email“:”myemail @ mycompany。com“, ”username“:”mynickname“ }” $ resource会让我更容易吗?无论如何,我需要“加入”这些对象。这不正确吗? – bkotyik

回答

0

您可以使用,而不是一个for环路关闭一个.forEach遍历i

userlist.data.forEach(function(user, i){ 
     MyService.GetUser(user.uid). 
      then(function(user) 
      { 
       $scope.groups[i].name = user.data.name; //So this is WRONG! 
      }); 
    } 

或者你可以创建一个映射与.map和使用$q.all使所有更新的曾经:

$q.all(userlist.data.map(function(user){ 
     return MyService.GetUser(user.uid)) 
}).then(function(users){ 
     // assign to scope, users is an array here and you can use indices 
}); 

尽管真实和实际的解决方法是不要让n用户致电n用户,而是创建一种方法,该方法接受服务器上的多个UID并一次为它们提取所有数据,因为它将减少系统的负载并提高执行速度,因为它不会导致往返和http请求。

+0

感谢您的回答。你的第一个例子不会减慢网页的加载时间?我的意思是forEach使服务调用同步,所以控制器将等待,直到forEach完成,这可能非常耗时。 在您的第二个解决方案中,我如何检索标记?您能否将我与这种数据映射相关的文章链接起来?我真的不知道这件事。谢谢。 – bkotyik

+0

@bkotyik它的做法是'.forEach'而不是'for'不会让魔法变成同步的,它只是同步地进行调用(注意不同之处,调用仍然是异步的)。在第二个示例中,您可以通过将'users [i]与$ scope.groups [i]'匹配来检索索引,那么您就拥有了整个数组。尽管如此,你的解决方案确实改变了后端API。 –

+0

好的,明白了。谢谢! – bkotyik