前言
本文主要针对 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 和 service 的职能分离,并且 controller 完全不依赖 http 而只是依赖 service 传递的事件和数据。再编写测试代码时,其逻辑也会变得简单。并且多个 controller 可以调用一个 service 中相同的方法,而不是通过曾经那种复制的方法来解决。
分层编写代码的最终目的无非就是:
- 增加代码的复用性;
- 代码责任简单,不会又做保姆又做司机,可读性强容易理解;
- 编写测试代码的时候容易编写;
- 减少对一些框架和环境插件的依赖;
- 修改逻辑时最小幅度的修改代码
- 数据层发生变更修改 Service,UI 层有变化则修改 Controller。不用担心改 controller 把 service 也一起带到沟里的情况发生。
最后
AngularJS 在许多框架的设计方面与 Java 的 Spring 非常类似,如果有一定的 Java 基础应该很能理解并写出分层的代码。
FROM
作者:AkiraPan
链接:https://www.jianshu.com/p/1e1aaf0fd30a
来源:简书