初学者的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
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

AngularJS中如何对Controller与Service进行分层设计与编码的更多相关文章

  1. angularjs中provider,factory,service的区别和用法

    angularjs中provider,factory,service的区别和用法 都能提供service,但是又有差别 service 第一次被注入时实例化,只实例化一次,整个应用的生命周期中是个单例 ...

  2. AngularJS中的Provider们:Service和Factory等的区别

    引言 看了很多文章可能还是不太说得出AngularJS中的几个创建供应商(provider)的方法(factory(),service(),provider())到底有啥区别,啥时候该用啥,之前一直傻 ...

  3. angularJS中directive与controller之间的通信

    当我们在angularJS中自定义了directive之后需要和controller进行通讯的时候,是怎么样进行通讯呢? 这里介绍3种angular自定义directive与controller通信的 ...

  4. [译]AngularJS中几种Providers(Factory, Service, Provider)的区别

    原文: http://blog.xebia.com/2013/09/01/differences-between-providers-in-angularjs/ 什么是Provider? Angula ...

  5. AngularJS中Model和Controller传值问题

    最近由于工作原因,开始写点前端的东西.前两天刚开始了解AngularJS这门技术,当然,新手免不了会爬坑! 今天分享一篇关于--> 模型传参给Controller的实例: 需求: 具体是  首先 ...

  6. 八、angularjs 中 filter在controller中的使用--避免多次遍历

    filter在html页面的使用司空见惯,比如: filter在controller中使用可以避免多次使用angular.foreach,来进行遍历.例如: 如果使用filter,则会让代码简洁而且明 ...

  7. AngularJS 中 Provider 的用法及区别

    在一个分层良好的 Angular 应用中,Controller 这一层应该很薄.也就是说,应用里大部分的业务逻辑和持久化数据都应该放在 Service 里. 为此,理解 AngularJS 中的几个 ...

  8. 怎么理解angularjs中的服务?

    AngularJS中的服务其实就是提供一种方式抽取共用类库 比如说一些工具类方法,我们传统的做法就是自己写个 utility 类,把相关的工具方法填充到utility里面去,最后把utility类放到 ...

  9. AngularJS中使用Directive、Controller、Service

    AngularJS是一款非常强大的前端MVC框架.同时,它也引入了相当多的概念,这些概念我们可能不是太熟悉. (1)Directive 指令 (2)Controller 控制器 (3)Service ...

随机推荐

  1. 2013.7.19 STL库的学习

    STL提供了一组表示容器,迭代器,函数对象和算法的模板. 容器是一个与数组类似的单元,可以存储若干个值.容器是同质的,即存储的值的类型一样. 算法是完成特定任务的处方. 迭代器能够用来遍历容器的对象, ...

  2. knockoutJS 快速上手

    翻译:Knockout 快速上手 - 3: knockoutJS 快速上手 许多时候,学会一种技术的有效方式就是使用它解决实际中的问题.在这一节,我们将学习使用 Knockout 来创建一个常见的应用 ...

  3. C/C++基础知识总结——数组、指针域、字符串

    1. 数组 1.1 数组作为函数参数 (1) 如果使用数组作为函数的参数,则实参和形参都是数组名,且类型要相同.数组名做参数时传递的是地址 (2) 使用方法: void rowSum(int a[][ ...

  4. UAC权限

    .NET中提升UAC权限的方法总结   [题外话] 从Vista开始,由于增加了UAC(用户账户控制,User Account Control)功能,使得管理员用户平时不再拥有能控制所有功能的管理员权 ...

  5. MySQL关联查询总结

    MySQL中经常使用关联查询,有机会总结下: 1 left join(左联查询): 返回包括左表中的所有记录和右表中联接字段相等的记录 例:select * from a left join b on ...

  6. Event处理

    Event处理 今天抽时间写了一部分Event处理方面的函数愈发的觉得jQuery的优秀,自己前期的想法太粗糙,造成后面这些函数参数很多,操作很很不直观,看样子是要重构的节奏,还好小伙儿伴们安慰,架构 ...

  7. GitHub上搭建个人网站

    大致如下步骤: 1.注册Git账号 2.创建SSH keys 3.新建repository --- 4.设置网站 5.clone库到本地 6.提交.上传 7.预览 本教程默认你了解GitHub的基础之 ...

  8. MSSQL Server查询优化方法(转)

    核心提示:查询速度慢的原因很多,常见如下几种 查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3. ...

  9. Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息

    Lucene学习-深入Lucene分词器,TokenStream获取分词详细信息 在此回复牛妞的关于程序中分词器的问题,其实可以直接很简单的在词库中配置就好了,Lucene中分词的所有信息我们都可以从 ...

  10. LigerUI权限系统之菜单管理

    菜单管理跟上篇的组织结构实现方式差不多,所以不存在多大的问题.还是老样,先上图,再看代码.菜单管理界面 菜单管理添加: 菜单管理修改: 前端完整代码: @section headerScripts{ ...