我的应用程序中有一个基本工厂,可以处理API调用。目前,我正在使用以下形式:
.factory('apiFactory', function($http){ var url = 'http://192.168.22.8:8001/api/v1/'; return { getReports: function() { return $http.get(url+'reports').then(function(result) { return result; }); }, getReport: function(id) { return $http.get(url+'report/'+id).then(function(result) { return result; }); } } })
在我的控制器中,我正在像这样处理诺言:
.controller('exampleController', function($scope, apiFactory) { apiFactory.getReports().then( function(answer) { if (answer.status==200){ if (answer.data.status == "error"){ // DISPLAY ERROR MESSAGE console.log(answer.data.msg); } } else{ // THROW error console.log('error: ', answer); } }, function(error){ console.log('error: ', answer); } ); } } })
看来我可以将promise处理移至Factory,而不是在控制器中执行,但是我不确定这是否会带来比小型控制器更多的好处。
有人可以解释有关此模式的最佳做法吗?
最终由您自己决定要向服务调用者提供多少数据。如果需要,您可以肯定地将HTTP响应对象返回给调用者,并让他们处理响应(顺便说一下,如果已解决而不是拒绝了诺言,则始终为HTTP 2xx)。
但是,如果您想将调用者与数据到达的方式(可能是缓存的或通过其他机制提供)的细节隔离开来,并且如果需要对数据进行后处理,则建议在服务。
这是一个例子:
.factory("apiService", function($http, $q){ var url = 'http://192.168.22.8:8001/api/v1/'; return { getReports: function() { return $http.get(url+'reports').then(function(result) { var data = result.data; if (data === "something I don't accept"){ return $q.reject("Invalid data"); } var processedData = processData(data); return processedData; }) .catch(function(err){ // for example, "re-throw" to "hide" HTTP specifics return $q.reject("Data not available"); }) }, // same idea for getReport } });
这样,控制器就无需关心底层机制了,它所获得的仅仅是数据或拒绝。
.controller('exampleController', function($scope, apiService) { apiService.getReports() .then(function(reports){ $scope.reports = reports; // actual reports data }); })
题外话:
注意如何将服务名称从更改"apiFactory"为"apiService"。我想指出这一点,以消除可能的误解。无论您使用.factory或者.service或者.value你可以注射什么始终是一个 服务 实例。.factory只是 如何 实例化此服务的机制,因此名称"apiFactory"不正确。这里唯一的“工厂”是您注册的功能.factory(当然可以是匿名的):
"apiFactory"
"apiService"
.factory
.service
.value
.factory("fooSvc", function fooSvcFactory(){ return { getFoo: function(){...} } })