我在角度服务中遇到了承诺问题。我有一个方法getArea
的服务,它应该返回服务区域的名称。该服务从API获取服务区域。当getArea
获取服务区域时,它会找到所请求区域的名称,并应返回它。但是,我的代码不起作用 - 我进入了无限循环。我想我误解了如何使用承诺?
SupplierService:
var servicePromise;
var getServices = function(){
if( !servicePromise ){
servicePromise = $http.get('/api/services')
.then(function(res){
return res.data.data;
});
}
return servicePromise;
};
var myService = {
getServices : getServices,
getArea : function(questionnaireId){
getServices().then(function(services){
// ...
return "hello world";
});
}
};
return myService;
控制器:
$scope.supplierService = SupplierService;
查看:
<div>
<b>Area:</b> {{ supplierService.getArea(r.questionnaireId) }}
</div
我希望视图显示“Area:hello world”,但会进入无限循环。
更新1:我在服务中添加了getServices
作为公共功能,可以从控制器访问它,如下所示:
SupplierService.getServices().then(function(d){
$scope.services = d;
});
因此我猜问题出现在getArea
方法中?
更新2:我的回答是https://stackoverflow.com/a/12513509/685352。我想缓存结果。
更新3:这是 plunker 。如果您尝试从视图中访问supplierService.getArea(100)
- 浏览器将不会响应。
答案 0 :(得分:2)
您的服务应该更像这样:
var getServices = function(){
var deferred = $q.deferred();
$http.get('/api/services')
.then(function(res){
deferred.resolve(res.data)
});
return deferred.promise;
};
请注意,在创建延迟时,必须返回deferred.promise(实际的promise),然后在异步调用返回时,必须根据需要调用deferred.resolve或deferred.rejected(以触发成功或错误函数)分别地)
轻微添加我有一个plunkr显示从服务中获取数据到控制器的几种方法,因为这是开发人员进入Angular的常见问题
http://plnkr.co/edit/ABQsAxz1bNi34ehmPRsF?p=info
这不是绝对的最佳实践,因为我试图尽可能简单,但基本上显示了三种不同的方式来“共享”您的数据,请记住这些方法中的一些依赖于angular.copy,这意味着服务的属性存储数据必须是一个Object或一个数组(原始类型将无法工作,因为无法共享引用)。
这是一个重写,包括内联函数:
var myService = {
var dataLoaded = false;
var data = {}; //or = [];
getServices : function(){
var deferred = $q.defer();
if( !dataLoaded ){
$http.get('/api/services').then(function(res){
angular.copy(res.data, myService.data);
deferred.resolve(myService.data);
}, function(err){
deferred.reject("Something bad happened in the request");
});
}
else
{
deferred.resolve(myService.data);
}
return deferred.promise;
}
};
return myService;
为了解释,我使用$ q服务创建了一个新的承诺,您需要将其注入服务功能。这允许我使用我已经拥有的数据来解决该承诺,或者调用该服务并解析该数据,但在这两种情况下使用它时,假设您将获得一个承诺,因此处理异步操作。如果要加载多个数据集,可以使用对象来存储标志而不是单个布尔值。
答案 1 :(得分:0)
我想如果你返回$ http回调?
//$http.get('/someUrl').success(successCallback);
var getServices = function(){
return $http.get('/api/services');
};
getServices.success(function(services){
// ...
return "hello world";
});
}