Angular开发者指南(五)服务
服务
AngularJS服务是使用依赖注入(DI)连接在一起的可替代对象。 可以使用服务在整个应用程式中整理和分享程式码。
AngularJS服务有:
- 延迟初始化 - AngularJS只在应用程序组件依赖它时实例化服务。
- 单例 - 依赖于服务的每个组件获取对服务工厂生成的单个实例的引用。
AngularJS提供了几个有用的服务(如$http),但对于大多数应用程序,你也想创建自己的。像其他核心的AngularJS标识符一样,内置服务总是以$开头(例如$http)。
使用服务
要使用AngularJS服务,请将其添加为依赖于依赖于服务的组件(控制器,服务,过滤器或指令)的依赖项。 AngularJS的依赖注入子系统负责其余的。
index.html
<div id="simple" ng-controller="MyController" ng-app="myServiceModule">
<p>让我们尝试这个简单的通知服务,注入到控制器</p>
<input ng-init="message='test'" ng-model="message" >
<button ng-click="callNotify(message);">NOTIFY</button>
<p>(必须点击3次才能看到提醒)</p>
</div>
script.js
angular.
module('myServiceModule', []).
controller('MyController', ['$scope', 'notify', function($scope, notify) {
$scope.callNotify = function(msg) {
notify(msg);
};
}]).
factory('notify', ['$window', function(win) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length === 3) {
win.alert(msgs.join('\n'));
msgs = [];
}
};
}]);
protractor.js
it('should test service', function() {
expect(element(by.id('simple')).element(by.model('message')).getAttribute('value'))
.toEqual('test');
});
需要点击三次NOTIFY按钮才会出现弹出框内容
创建服务
应用程序开发人员可以使用AngularJS模块注册服务的名称和服务工厂函数来自由定义自己的服务。
服务工厂函数生成表示对应用程序其余部分的服务的单个对象或函数。 服务返回的对象或函数被注入到指定对服务的依赖性的任何组件(控制器,服务,过滤器或指令)中。
注册服务
服务通过Module API注册到模块。 通常您使用Module factory API注册服务:
var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
var shinyNewServiceInstance;
// 构造shinyNewServiceInstance的工厂函数体
return shinyNewServiceInstance;
});
此时不是注册服务实例,而是一个在调用时将创建此实例的工厂函数。
依赖
服务可以有自己的依赖。 就像在控制器中声明依赖项一样,可以通过在服务的工厂函数签名中指定依赖性来声明它们。
下面的示例模块有两个服务,每个具有各种依赖关系:
var batchModule = angular.module('batchModule', []);
/**
*`batchLog'服务允许消息在内存中排队,并且每50秒刷新到console.log
*/
batchModule.factory('batchLog', ['$interval', '$log', function($interval, $log) {
var messageQueue = [];
function log() {
if (messageQueue.length) {
$log.log('batchLog messages: ', messageQueue);
messageQueue = [];
}
}
// 开始定期检查
$interval(log, 50000);
return function(message) {
messageQueue.push(message);
}
}]);
/**
*`routeTemplateMonitor`监视每个`$ route`更改,并通过`batchLog`服务记录当前模板
*/
batchModule.factory('routeTemplateMonitor', ['$route', 'batchLog', '$rootScope',
function($route, batchLog, $rootScope) {
return {
startMonitoring: function() {
$rootScope.$on('$routeChangeSuccess', function() {
batchLog($route.current ? $route.current.template : null);
});
}
};
}]);
在示例中,需要注意的是:
- batchLog服务取决于内置的$interval和$log服务。
- routeTemplateMonitor服务取决于内置的$route服务和$rootscope和我们的自定义batchLog服务。
- 两个服务都使用数组符号来声明它们的依赖关系。
- 数组中标识符的顺序与工厂函数中参数名称的顺序相同。
还可以通过模块的配置函数中的$provide服务注册服务:
angular.module('myModule', []).config(['$provide', function($provide) {
$provide.factory('serviceId', function() {
var shinyNewServiceInstance;
// 构造shinyNewServiceInstance的工厂函数体
return shinyNewServiceInstance;
});
}]);
这种技术通常用于单元测试中来模拟服务的依赖。
单元测试
以下是来自上面的创建服务示例的通知服务的单元测试。 单元测试示例使用Jasmine spy(mock),而不是真正的浏览器alert。
var mock, notify;
beforeEach(module('myServiceModule'));
beforeEach(function() {
mock = {alert: jasmine.createSpy()};
module(function($provide) {
$provide.value('$window', mock);
});
inject(function($injector) {
notify = $injector.get('notify');
});
});
it('should not alert first two notifications', function() {
notify('one');
notify('two');
expect(mock.alert).not.toHaveBeenCalled();
});
it('should alert all after third notification', function() {
notify('one');
notify('two');
notify('three');
expect(mock.alert).toHaveBeenCalledWith("one\ntwo\nthree");
});
it('should clear messages after alert', function() {
notify('one');
notify('two');
notify('third');
notify('more');
notify('two');
notify('third');
expect(mock.alert.calls.count()).toEqual(2); expect(mock.alert.calls.mostRecent().args).
toEqual(["more\ntwo\nthird"]);
});
Angular开发者指南(五)服务的更多相关文章
- ZooKeeper开发者指南(五)
引言 这个文档是为了想利用ZooKeeper的协调服务来创建分布式应用的开发者提供的指南.它包括概念和实践的信息. 这个文档的一开始的的四部分呈现了不同ZooKeeper高级概念的的讨论.理解Zook ...
- Angular开发者指南(二)概念概述
template(模板):带有附加标记的模板HTML directives(指令):使用自定义属性和元素扩展HTML model(模型):用户在视图中显示的数据,并与用户进行交互 scope(作用域) ...
- Angular开发者指南(一)入门介绍
什么是Angular AngularJS是动态Web应用程序的结构框架. 它允许您使用HTML作为模板语言,并允许您扩展HTML的语法以清晰,简洁地表达应用程序的组件.AngularJS的数据绑定和依 ...
- Angular开发者指南(七)依赖注入
依赖注入 依赖注入(DI)是一种软件设计模式,处理组件如何获取其依赖关系. AngularJS注入器子系统负责创建组件,解析它们的依赖关系,并根据请求将它们提供给其他组件. 使用依赖注入 DI遍布An ...
- Angular开发者指南(六)作用域
什么是作用域? 作用域是引用应用程序模型的对象. 它是表达式的执行上下文. 作用域以层次结构排列,模仿应用程序的DOM结构,它可以观察表达式和传播事件. 作用域的特征 Scope提供API($watc ...
- Angular开发者指南(四)控制器
了解控制器controller 在AngularJS中,Controller由JavaScript构造函数定义,用于扩充AngularJS Scope. 当控制器通过ng-controller指令连接 ...
- Angular开发者指南(三)数据绑定
数据绑定 AngularJS应用程序中的数据绑定是模型和视图组件之间的数据的自动同步. AngularJS实现数据绑定的方式可以将模型视为应用程序中的单一来源. 视图是模型在任何时候的投影. 当模型更 ...
- [译]AngularJS 1.3.0 开发者指南(一) -- 介绍
[译]AngularJS 1.3.0 开发者指南(一) -- 介绍 Angular是什么 ? AngularJS是一款针对动态web应用的结构框架. 它可以让像使用模板语言使用HTML, 并且可以扩展 ...
- [译]AngularJS 1.3.0 开发者指南(一) -- 介绍 (转)
http://www.cnblogs.com/lzj0616/p/6440563.html [译]AngularJS 1.3.0 开发者指南(一) -- 介绍 Angular是什么 ? Angular ...
随机推荐
- SQL基础教程(第2版)第5章 复杂查询:5-2 子查询
第5章 复杂查询:5-2 子查询 ● 一言以蔽之,子查询就是一次性视图( SELECT语句).与视图不同,子查询在SELECT语句执行完毕之后就会消失.● 由于子查询需要命名,因此需要根据处理内容来指 ...
- gcc编译出现:error: invalid operands to binary & (have ‘char *’ and ‘int *’)
/************************************************************************* > File Name: ptr_varia ...
- UML-架构分析-阶段
初始阶段:架构概念验证原型--->确定其可行性 细化阶段:因素表.技术备忘录.SAD(软件架构文档) 移交阶段:可能会修改SAD->确保与最终部署版本的一致性 后续进化循环:重温架构性因素 ...
- 2019年阿里java面试题
一.JVM与性能优化 描述一下 JVM 加载 Class 文件的原理机制? 什么是类加载器? 类加载器有哪些? 什么是tomcat类加载机制? 类加载器双亲委派模型机制? Java 内存分配? Jav ...
- MySQL--SQL分类
SQL语句主要可以划分为以下3个类别: DDL(Data Definition Languages)语句:数据定义语言,这些语句定义了不同的数据段.数据库.表.列.索引等数据库对象. 常用的语句关键字 ...
- Android开发—错误记录1:W/System.err: java.net.ConnectException: Connection refused
W/System.err: java.net.ConnectException: Connection refused 前台访问后台时,出现访问被拒绝情况:W/System.err: java.net ...
- Momentum
11.6 Momentum 在 Section 11.4 中,我们提到,目标函数有关自变量的梯度代表了目标函数在自变量当前位置下降最快的方向.因此,梯度下降也叫作最陡下降(steepest desce ...
- IDA解析so文件异常(Binary data is incorrect maximum possible value is xx)
错误信息 Binary data is incorrect maximum possible value is 0 错误原因 so文件损坏 或者ida换成32 解决办法 重新获得so文件,或者调整id ...
- Channels(纪念一下卡我心态的一道题)
链接:https://ac.nowcoder.com/acm/contest/3947/C来源:牛客网 题目描述 Nancy喜欢学习,也喜欢看电视. 为了想了解她能看多长时间的节目,不妨假设节目从时刻 ...
- LA 3882 经典约瑟夫环问题的数学递推解法
就是经典约瑟夫环问题的裸题 我一开始一直没理解这个递推是怎么来的,后来终于理解了 假设问题是从n个人编号分别为0...n-1,取第k个, 则第k个人编号为k-1的淘汰,剩下的编号为 0,1,2,3. ...