AngularJS中如何对Controller与Service进行分层设计与编码
前言
本文主要针对AngularJS的初学者而编写的一篇关于如何在AngularJS框架下更好的编写代码的一个指南。下文将对AngularJS进行简称,替代为NG。
初学者的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中相同的方法,而不是通过曾经那种复制的方法来解决。
分层编写代码的最终目的无非就是
- 增加代码的复用性;
- 代码责任简单,不会又做保姆又做司机,可读性强容易理解;
- 编写测试代码的时候容易编写;
- 减少对一些框架和环境插件的依赖;
- 修改逻辑时最小幅度的修改代码
- 数据层发生变更修改Service,UI层有变化则修改Controller。不用担心改controller把service也一起带到沟里的情况发生。
最后的最后
AngularJS在许多框架的设计方面与Java的Spring非常类似,如你有一定的Java基础应该很能理解为赢编写出分层的代码。