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
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM