一尘不染

Angular最佳实践:在工厂还是在控制器中承诺?

angularjs

我的应用程序中有一个基本工厂,可以处理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,而不是在控制器中执行,但是我不确定这是否会带来比小型控制器更多的好处。

有人可以解释有关此模式的最佳做法吗?


阅读 282

收藏
2020-07-04

共1个答案

一尘不染

最终由您自己决定要向服务调用者提供多少数据。如果需要,您可以肯定地将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(当然可以是匿名的):

.factory("fooSvc", function fooSvcFactory(){
   return {
      getFoo: function(){...}
   }
})
2020-07-04