AngularJS中如何对Controller与Service进行分层设计与编码

  

初学者的Controller

在我们当接触NG后,如需要通过访问远程的API获取一系列的数据进行显示,通常我的Controller代码会写成下面的样子:

angular.module('demo')
.controller('myCtrl',['$scope','$http', function($scope,$http){
  $http.get("xxx")
       .success(function(response) 
           {
               $scope.data = response.data;
           });
}]);

这样的在功能上是没有问题的,但是会导致Controller除了负担了与View层的$scope变量的初始化和防范定义还需要额外注入http进行远程的数据调用。
如当调用API的代码是会大量被引用、或是API变更时候会导致大面的修改Controller代码。

分离Service

Service层和Controller层的分工

我们将原来全部集中在Controller中代码拆分成两个层面:

  • service层:主要负责数据交互和数据处理、处理一些业务领域上的逻辑;
  • controller层:主要负责初始化$scope的变量用于传递给view层,并且处理一些页面交互产生的逻辑;

    什么情况下需要编写Service

    当一个功能是设计远程API调用、数据集、业务领悟复杂逻辑、将会大量重复的运算方法时就可以考虑将代码以service形式注入controller层。

编写Service

将原先的代码从Controller中抽离处理,代码如下:

angular.module('demo')
.service('myService',['$http',function($http){
return {
    getData:function(){
        return $http.get("xxx");
    }
}
}]);

则Controller的代码将会被注入myService用于获取相关的数据

 angular.module('demo')
.controller('myCtrl',['$scope','myService', function($scope,$http,myService){
 myService.getData().success(function(response) 
           {
               $scope.data = response.data;
           });
}]);

基本上这样的代码看上去很不错了,但是我们依旧在Controller层处理了通讯时的回调函数success,这样controller虽然直接依赖http了,但是还是间接的需要处理http。

在Service层处理通讯回调,将业务回调传递给Controller层

这里需要引入deffered将http的通讯级的回调在Service层处理完后,再重新交由controller去处理其他的问题。

angular.module('demo')
.service('myService',['$http','$q',function($http,$q){
return {
    getData:function(){
        var deferred = $q.defer();
        var promise = $http.get("xxx");
         promise.then(
                  // 通讯成功的处理
                  function(answer){
                    //在这里可以对返回的数据集做一定的处理,再交由controller进行处理
                    answer.status = true;
                    deferred.resolve(answer);
                  },
                  // 通讯失败的处理
                  function(error){
                    // 可以先对失败的数据集做处理,再交由controller进行处理
                    error.status = false;
                    deferred.reject(error);
                  });
                //返回promise对象,交由controller继续处理成功、失败的业务回调
        return deferred.promise;
    }
}
}]);

相应的在controller中我们也可以进行相关事件的处理,修改代码如下

 angular.module('demo')
.controller('myCtrl',['$scope','myService', function($scope,myService){
 myService.getData().then(
     function(answer){
         $scope.data = answer;
     },
     function(error){
         $scope.error = error;
     }
 );
}]);

这样controller和servic的职业分离,并且controller完全不依赖http而只是依赖service传递的事件和数据。再编写测试代码时,其逻辑也会变得简单。并且多个controller可以调用一个service中相同的方法,而不是通过曾经那种复制的方法来解决。
分层编写代码的最终目的无非就是

  1. 增加代码的复用性;
  2. 代码责任简单,不会又做保姆又做司机,可读性强容易理解;
  3. 编写测试代码的时候容易编写;
  4. 减少对一些框架和环境插件的依赖;
  5. 修改逻辑时最小幅度的修改代码
  6. 数据层发生变更修改Service,UI层有变化则修改Controller。不用担心改controller把service也一起带到沟里的情况发生。

    最后的最后

    AngularJS在许多框架的设计方面与Java的Spring非常类似,如你有一定的Java基础应该很能理解为赢编写出分层的代码。



文/AkiraPan(简书作者)
原文链接:http://www.jianshu.com/p/1e1aaf0fd30a
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
原文地址:https://www.cnblogs.com/Uncle-Maize/p/5916663.html