Javascript 角度服务中的$http承诺

Javascript 角度服务中的$http承诺,javascript,angularjs,Javascript,Angularjs,我有一个角度服务承诺的问题。我有一个带有方法getArea的服务,该方法应该返回服务区域的名称。该服务从API获取服务区域。当getArea获取服务区域时,它会找到请求区域的名称,并应返回该名称。然而,我的代码不起作用——我进入了一个无限循环。我想我误解了如何使用承诺 供应商服务: var servicePromise; var getServices = function(){ if( !servicePromise ){ servicePromise = $http.

我有一个角度服务承诺的问题。我有一个带有方法
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
控制器:

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
查看:

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
因此,我猜问题出在
getArea
方法中


更新2:这个答案启发了我。我想缓存结果



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

您的服务应该更像这样:

SupplierService.getServices().then(function(d){
    $scope.services = d;
});
var getServices = function(){
    var deferred = $q.deferred();
    $http.get('/api/services')
            .then(function(res){
                deferred.resolve(res.data)
            });
    return deferred.promise;
};
请注意,在创建延迟调用时,必须返回deferred.promise(实际承诺),然后在异步调用返回时,必须根据需要调用deferred.resolve或deferred.rejected(分别触发成功或错误函数)

小补充我有一个plunkr,展示了从服务获取数据到控制器的几种方法,因为这是开发人员进入应用程序的常见问题

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

以下是包含函数内联的重写:

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

我认为如果返回$http回调

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


var getServices = function(){
    return $http.get('/api/services');

};

getServices.success(function(services){
// ...
           return "hello world";
        });
   }

+1$q服务,Angular的精益承诺服务,将被注入。您当然可以返回$http.get('/api/services'),因为它已经是一个承诺。很好的一点是,我倾向于这样做,并使用一个对象来检查我是否已经加载了数据(为我将在服务中进行的每个服务调用存储一个属性,以了解数据是否已加载),我想我已经习惯了“显式”地进行此操作但是正如您所说,使用get返回的HttpPromise也是一个很好的解决方案。
getArea
方法中的问题不是吗?我实际上也返回了getServices方法,当异步调用返回时,我在控制器中得到了服务。@Sweedo不确定这里还缺少了什么,您是否仍然遇到了问题最后一个版本的代码,你能发布一个plunkr或JSFIDLE来显示你的问题吗?@shaunhusain我已经发布了一个plunkr,以及我的代码版本。它表明我的
getServices()
可以工作,但
getArea
不能。