angular服务中的$http承诺

$http promise in angular service

本文关键字:http 承诺 服务 angular      更新时间:2023-09-26

我在角度服务中遇到了promise问题。我有一个方法为getArea的服务,它应该返回服务区域的名称。服务从API获取服务区域。当getArea获取服务区域时,它会找到请求区域的名称,并应该返回它。然而,我的代码不起作用——我进入了一个无限循环。我想我误解了如何使用承诺?

供应商服务:

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

我希望视图显示"区域:你好世界",但进入了一个无限循环。


更新1:我在服务中添加了getServices作为公共功能,可以从控制器访问它,如下所示:

SupplierService.getServices().then(function(d){
    $scope.services = d;
});

所以我想问题出在getArea方法上?


更新2:我受到了这个答案的启发https://stackoverflow.com/a/12513509/685352.我想缓存结果。


更新3:这里有一个plunker。如果您尝试从视图访问supplierService.getArea(100),浏览器将不会响应。

您的服务应该更像这样:

var getServices = function(){
    var deferred = $q.deferred();
    $http.get('/api/services')
            .then(function(res){
                deferred.resolve(res.data)
            });
    return deferred.promise;
};

注意,当您创建一个deferred时,您必须返回deferred.promise(实际的promise),然后当您是异步调用返回时,必须根据需要调用deferred.resolve或deferred_rejected(分别触发成功或错误函数)

小补充一点,我有一个plunkr展示了一些将数据从服务获取到控制器中的方法,因为这是进入Angular 的开发人员的常见问题

http://plnkr.co/edit/ABQsAxz1bNi34ehmPRsF?p=info

这并不是绝对的最佳实践,因为我试图让它尽可能简单,但基本上展示了三种不同的"共享"数据的方法。请记住,其中一些方法依赖于angular.copy,这意味着存储数据的服务的属性必须是Object或Array(基元类型不起作用,因为引用无法共享)。

这是一个包含内联函数的重写:

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服务创建了一个新的promise,您需要将其注入到服务函数中。这使我可以用我已经拥有的数据来解析该promise,或者调用服务并解析该数据,但在这两种情况下,当使用它时,都假设您只会得到一个promise,因此正在处理异步操作。如果要加载多个数据集,则可以使用一个对象来存储标志,而不是使用单个布尔值。

我认为如果您返回$http回调?

//$http.get('/someUrl').success(successCallback);

var getServices = function(){
    return $http.get('/api/services');
};
getServices.success(function(services){
// ...
           return "hello world";
        });
   }