AngularJS:多承诺不规律解析 [英] AngularJS: multiple promises resolving erratically
问题描述
我分配两个集合到我在控制器范围;无论是从服务包RestAngular来回报承诺。每间单独返回我想收集,但是当我分配既$范围其中之一从来没有解决(这是相同的一个失败,无论他们所在的顺序)。
如果我登录再次调用违规服务,然后LO安慰你看原来的分配完美的作品。
这些服务都工作pretty大致相同的:
.factory('角色',['Restangular','$ Q',函数(Restangular,$ Q){
变种_collection = [];
VAR _roleService = Restangular.all('角色'); 返回{
的GetList:功能(){
//返回_roleService.getList();
变种listDeferred = $ q.defer();
_roleService.getList()
。然后(功能(名单){
listDeferred.resolve(名单);
_collection =清单;
});
返回listDeferred.promise;
}
}
}
])
和控制器规定如下(我已经离开了的console.log,但删除它会导致$ scope.roles永远不会解决):
.controller('ResourceCtrl',['$范围,资源,角色,函数($范围,资源,角色){
$ scope.roles = Role.getList();
$ scope.resources = Resource.getList(); 的console.log(Role.getList());
}])
一切都在角做,所以我不认为我缺少一个$应用 - 但除非我的错误绊倒必须有什么问题我的code ...
修改
我发现了什么导致了错误,但没有一个解决方案。我的资源服务是非常相似的作用,但是因为资源有角色,我注入作用到资源并用它来个别元素链接在一起。有一次,我删除了所有行范围/承诺的东西回来了。
我的猜测让我回想起:我怎么联系起来的服务可靠(即所以用角色字段资源可以在服务级别重视他们相应的角色对象)。
下面是我的资源:
.factory('资源',['Restangular','$ Q','角色',
功能(Restangular,$ Q,角色){
VAR _resourceService = RestAngular.all('资源');
VAR _roleService =作用; VAR _convertObjectsToUrls =功能(项目){
对于(项VAR属性){
如果(item.hasOwnProperty(财产)及和放大器; typeof运算(项目[物业])=='对象'和;&安培;!项目[物业] = NULL){
项目[物业] =项目[物业]的.url;
}
}
归还物品;
} VAR _convertUrlsToObjects =功能(项目){
对于(项VAR属性){
如果(item.hasOwnProperty(财产)及和放大器; typeof运算(项目[物业])=='串'和;&放大器;项目[物业] ='!'和;&安培;物业!='URL'和;&安培;项目[物业] .substr(0,4)=='HTTP'){
/ *这个换行符IT * /项目[物业] = _roleService.getByUrl(项目[物业]);
}
}
归还物品;
} VAR _getIdFromUrl =功能(URL){
VAR pathElements = url.split('/')
返回pathElements [pathElements.length - 2]
} VAR _cleanParams =功能(项目){
对于(项VAR属性){
如果(item.hasOwnProperty(财产)){
项目[物业] =不确定;
}
}
归还物品;
} 返回{
添加:函数(项目){
变种responseDeferred = $ q.defer();
项目= _convertObjectsToUrls(项目); _resourceService.post(项目)
。然后(功能(响应){
响应= _convertUrlsToObjects(响应);
response.name = response.first_name +''+ response.last_name; _collection.push(响应);
responseDeferred.resolve(响应); 项目= _cleanParams(项目);
});
返回responseDeferred.promise;
},
编辑:函数(项目){
变种responseDeferred = $ q.defer();
VAR IDX = _collection.indexOf(项目);
项目= _convertObjectsToUrls(项目); item.customPUT(_getIdFromUrl(item.url))
。然后(功能(响应){
响应= _convertUrlsToObjects(响应);
response.name = response.first_name +''+ response.last_name; _collection.splice(IDX,1,响应)
responseDeferred.resolve(响应);
});
返回responseDeferred.promise;
},
删除:函数(项目){
变种responseDeferred = $ q.defer();
VAR IDX = _collection.indexOf(项目);
//项目= _convertObjectsToUrls(项目); item.customDELETE(_getIdFromUrl(item.url),{})
。然后(功能(响应){
响应= _convertUrlsToObjects(响应); _collection.splice(IDX,1)
responseDeferred.resolve(响应);
});
返回responseDeferred.promise;
},
的GetList:功能(){
变种listDeferred = $ q.defer();
VAR列表= _resourceService.getList()
。然后(功能(名单){
_.each(列表功能(项指标,表){
项目= _convertUrlsToObjects(项目);
item.name = item.first_name +''+ item.last_name;
})
listDeferred.resolve(名单);
_collection =清单;
});
返回listDeferred.promise;
}
}
}
])
从那里资源服务来了,是否是很重要的不知道。既然你在你的角色的服务回报承诺,你可以做:
.controller('ResourceCtrl',['$范围','角色',函数($范围,角色){
Role.getList()。然后(功能(角色){
$ scope.roles =角色;
});
}])
另外,你可以让角度解析您的角色(如果你只是用在模板中的角色,例如)
.controller('ResourceCtrl',['$范围','角色',函数($范围,角色){
$ scope.roles = Role.getList();
}])
编辑:我也注意到了 VAR _collection = [];
这似乎没有必要。也许你也可以张贴code为资源服务?
您的角色服务的这code应该是足够了。
.factory('角色',['Restangular','$ Q',函数(Restangular,$ Q){
返回{
的GetList:功能(){
变种listDeferred = $ q.defer();
Restangular.all(角色)的GetList()。然后(功能(名单){
listDeferred.resolve(名单);
});
返回listDeferred.promise;
}
}
}
])
更进一步编辑:
这plunkr表明,在角1.2rc3的第一种方法:
http://embed.plnkr.co/SU5UMK7jNffXWnWiV1HE/$p$pview
但是,如果你尝试采取承诺的自动unrwapping的优势(这是在RC3 pcated德$ P $,你的运气了):
http://embed.plnkr.co/zdepkLCesYkj8pXYFTN2/$p$pview
I am assigning two collections into my scope in a controller; both come from services wrapping RestAngular and return promises. Each individually returns the collection I want, but when I assign both to $scope one of them never resolves (it's the same one that fails, no matter the order they're in).
If I log to console by calling the offending service again, then lo and behold the original assignment works perfectly.
The services both work pretty much the same:
.factory('Role', ['Restangular', '$q', function(Restangular, $q){
var _collection = [];
var _roleService = Restangular.all('roles');
return {
getList: function() {
// return _roleService.getList();
var listDeferred = $q.defer();
_roleService.getList()
.then(function(list) {
listDeferred.resolve(list);
_collection = list;
});
return listDeferred.promise;
}
}
}
])
and the controller is specified as follows (I've left the console.log in, but removing it causes $scope.roles to never resolve):
.controller('ResourceCtrl', ['$scope', 'Resource', 'Role', function($scope, Resource, Role) {
$scope.roles = Role.getList();
$scope.resources = Resource.getList();
console.log(Role.getList());
}])
Everything is done within Angular so I don't think I'm missing an $apply - but unless I've stumbled on a bug there must be something wrong with my code...
EDIT
I found out what's causing the error, but don't have a solution. My Resource service is very similar to the Role one, but because Resources have Roles, I inject Role into Resource and use it to link individual elements together. Once I deleted that line all the scope / promise stuff came back.
Which I guess takes me back to: how do I link services together reliably (i.e. so Resources with role fields can have the corresponding Role objects attached to them at the service level).
Here's my Resource:
.factory('Resource', ['Restangular', '$q', 'Role',
function(Restangular, $q, Role){
var _resourceService = RestAngular.all('resources');
var _roleService = Role;
var _convertObjectsToUrls = function(item) {
for (var property in item) {
if (item.hasOwnProperty(property) && typeof(item[property]) == 'object' && item[property] != null) {
item[property] = item[property].url;
}
}
return item;
}
var _convertUrlsToObjects = function(item) {
for (var property in item) {
if (item.hasOwnProperty(property) && typeof(item[property]) == 'string' && item[property] != '' && property != 'url' && item[property].substr(0,4) == 'http') {
/* THIS LINE BREAKS IT */ item[property] = _roleService.getByUrl(item[property]);
}
}
return item;
}
var _getIdFromUrl = function(url) {
var pathElements = url.split('/')
return pathElements[pathElements.length - 2]
}
var _cleanParams = function(item) {
for (var property in item) {
if (item.hasOwnProperty(property)) {
item[property] = undefined;
}
}
return item;
}
return {
add: function(item) {
var responseDeferred = $q.defer();
item = _convertObjectsToUrls(item);
_resourceService.post(item)
.then(function(response){
response = _convertUrlsToObjects(response);
response.name = response.first_name + ' ' + response.last_name;
_collection.push(response);
responseDeferred.resolve(response);
item = _cleanParams(item);
});
return responseDeferred.promise;
},
edit: function(item) {
var responseDeferred = $q.defer();
var idx = _collection.indexOf(item);
item = _convertObjectsToUrls(item);
item.customPUT(_getIdFromUrl(item.url))
.then(function(response){
response = _convertUrlsToObjects(response);
response.name = response.first_name + ' ' + response.last_name;
_collection.splice(idx, 1, response)
responseDeferred.resolve(response);
});
return responseDeferred.promise;
},
delete: function(item) {
var responseDeferred = $q.defer();
var idx = _collection.indexOf(item);
// item = _convertObjectsToUrls(item);
item.customDELETE(_getIdFromUrl(item.url), {})
.then(function(response){
response = _convertUrlsToObjects(response);
_collection.splice(idx, 1)
responseDeferred.resolve(response);
});
return responseDeferred.promise;
},
getList: function() {
var listDeferred = $q.defer();
var list = _resourceService.getList()
.then(function(list) {
_.each(list, function(item, index, list){
item = _convertUrlsToObjects(item);
item.name = item.first_name + ' ' + item.last_name;
})
listDeferred.resolve(list);
_collection = list;
});
return listDeferred.promise;
}
}
}
])
Not sure from where the Resource service comes and whether is is of importance. Since you return a promise in your Role service, you can just do:
.controller('ResourceCtrl', ['$scope', 'Role', function($scope, Role) {
Role.getList().then(function(roles){
$scope.roles = roles;
});
}])
Alternatively, you can let Angular resolve the role for you (if you are just using the roles in a template, for example)
.controller('ResourceCtrl', ['$scope', 'Role', function($scope, Role) {
$scope.roles = Role.getList();
}])
Edit: I also noticed the var _collection = [];
which seems not needed. Maybe you can also post the code for the Resource service?
This code of your Role service should be sufficient.
.factory('Role', ['Restangular', '$q', function(Restangular, $q){
return {
getList: function() {
var listDeferred = $q.defer();
Restangular.all('roles').getList().then(function(list) {
listDeferred.resolve(list);
});
return listDeferred.promise;
}
}
}
])
Even further edit:
This plunkr shows that in angular 1.2rc3 the first method works: http://embed.plnkr.co/SU5UMK7jNffXWnWiV1HE/preview
But if you were to try to take advantage of the automatic unrwapping of promises (which is deprecated in rc3, you are out of luck): http://embed.plnkr.co/zdepkLCesYkj8pXYFTN2/preview
这篇关于AngularJS:多承诺不规律解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!