我是AngularJS世界的新手,我面临着一个有趣的问题:
我创建了一个Angular工厂服务,它作为我正在调用的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返回给定组中的 userID-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(用户名)的参数列表扩展到GetUser(用户名,标记)。在这个标签中我可以放任何我想要的东西 在回调中检索。
所以我稍微修改了我的代码:
//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);
}
现在我可以在控制器中检索I的有效过去值:
修改后的控制器代码:
//...
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!
});
}
});
我的问题是:此解决方案在技术上是否正确?对于这样的问题,最佳做法是什么? AngularJS有这个工具吗?
ps:在这种情况下,修改REST服务API以返回用户名也不是解决方案。
提前致谢
答案 0 :(得分:0)
您可以使用.forEach
循环而不是关闭for
的{{1}}循环:
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
个用户,而是创建一个方法,在服务器上接受多个UID并立即为它们提取所有数据,因为它会加载系统更少,执行速度更快,因为它不会进行n
往返和http请求。