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

Squ*_*ler 3 javascript promise 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;
      });
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

在我的控制器中,我正在处理这样的承诺:

.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);
        }
      );
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

似乎我可以将承诺处理转移到我的工厂而不是在我的控制器中进行,但我不确定除了较小的控制器之外是否还有其他好处.

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

New*_*Dev 10

最终由您决定要向服务的调用者提供多少数据.如果需要,您肯定可以将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
  }
});
Run Code Online (Sandbox Code Playgroud)

然后控制器不需要关心底层机制 - 它获得的只是数据或拒绝.

.controller('exampleController', function($scope, apiService) {
   apiService.getReports()
     .then(function(reports){
        $scope.reports = reports; // actual reports data
     });
})
Run Code Online (Sandbox Code Playgroud)

无关:

请注意我是如何将服务名称更改"apiFactory""apiService".我想指出这一点,以消除可能的误解.无论您使用.factory或者.service或者.value你可以注射什么始终是一个服务实例..factory仅仅是一个机制如何此服务被实例化,所以这个名字"apiFactory"是用词不当.这里唯一的"工厂"是您注册的功能.factory(当然可以是匿名的):

.factory("fooSvc", function fooSvcFactory(){
   return {
      getFoo: function(){...}
   }
})
Run Code Online (Sandbox Code Playgroud)