服务

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开发者指南(五)服务的更多相关文章

  1. ZooKeeper开发者指南(五)

    引言 这个文档是为了想利用ZooKeeper的协调服务来创建分布式应用的开发者提供的指南.它包括概念和实践的信息. 这个文档的一开始的的四部分呈现了不同ZooKeeper高级概念的的讨论.理解Zook ...

  2. Angular开发者指南(二)概念概述

    template(模板):带有附加标记的模板HTML directives(指令):使用自定义属性和元素扩展HTML model(模型):用户在视图中显示的数据,并与用户进行交互 scope(作用域) ...

  3. Angular开发者指南(一)入门介绍

    什么是Angular AngularJS是动态Web应用程序的结构框架. 它允许您使用HTML作为模板语言,并允许您扩展HTML的语法以清晰,简洁地表达应用程序的组件.AngularJS的数据绑定和依 ...

  4. Angular开发者指南(七)依赖注入

    依赖注入 依赖注入(DI)是一种软件设计模式,处理组件如何获取其依赖关系. AngularJS注入器子系统负责创建组件,解析它们的依赖关系,并根据请求将它们提供给其他组件. 使用依赖注入 DI遍布An ...

  5. Angular开发者指南(六)作用域

    什么是作用域? 作用域是引用应用程序模型的对象. 它是表达式的执行上下文. 作用域以层次结构排列,模仿应用程序的DOM结构,它可以观察表达式和传播事件. 作用域的特征 Scope提供API($watc ...

  6. Angular开发者指南(四)控制器

    了解控制器controller 在AngularJS中,Controller由JavaScript构造函数定义,用于扩充AngularJS Scope. 当控制器通过ng-controller指令连接 ...

  7. Angular开发者指南(三)数据绑定

    数据绑定 AngularJS应用程序中的数据绑定是模型和视图组件之间的数据的自动同步. AngularJS实现数据绑定的方式可以将模型视为应用程序中的单一来源. 视图是模型在任何时候的投影. 当模型更 ...

  8. [译]AngularJS 1.3.0 开发者指南(一) -- 介绍

    [译]AngularJS 1.3.0 开发者指南(一) -- 介绍 Angular是什么 ? AngularJS是一款针对动态web应用的结构框架. 它可以让像使用模板语言使用HTML, 并且可以扩展 ...

  9. [译]AngularJS 1.3.0 开发者指南(一) -- 介绍 (转)

    http://www.cnblogs.com/lzj0616/p/6440563.html [译]AngularJS 1.3.0 开发者指南(一) -- 介绍 Angular是什么 ? Angular ...

随机推荐

  1. SQL基础教程(第2版)第8章 SQL高级处理:8-1 窗口函数

    第8章 SQL高级处理:8-1 窗口函数 ● 窗口函数可以进行排序.生成序列号等一般的聚合函数无法实现的高级操作.● 理解PARTITION BY和ORDER BY这两个关键字的含义十分重要. ■什么 ...

  2. HTML 回到顶部 浮动

    回到顶部 <div id="FloatDIV" style="position: absolute; top: 0px; z-index: 9999; backgr ...

  3. Linux安装maven超级详细步骤

    一 服务器联网情况下安装maven 1.安装wget命令 如果需要通过使用wget命令,直接通过网络下载maven安装包时,需要在linux系统中安装wget命令. yum -y install wg ...

  4. MVPR下的PHP分页教程

    这个PHP分页其实不难,现在就开始看看核心思路吧. 我习惯从最底层开始看起. 1. 首先用LIMIT偏移QUERY的指针 /* * get hot post by current page * @pa ...

  5. jQuery如何给DOM添加ID

    ID每个元素只能有一个,ID名同一页面也不能重复,addID方法是不需要的,和其他属性一样用attr方法就行了, $(singleTarget).attr('id','idName'); 更简单的 $ ...

  6. java学习——内部类(一)

    内部类 把一个类放在另一个类中定义,这个定义在其他内部的类被称为内部类,包含内部类 的类被成为外部类,Java从JDK1.1开始引入了内部类的定义. 内部类的作用: 内部类提供了更好的封装,可以把内部 ...

  7. 吴裕雄--天生自然 JAVA开发学习:流(Stream)、文件(File)和IO

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //使用 BufferedReader 在控制台读取 ...

  8. Leetcode(104)之二叉树的最大深度

    题目描述: 解题思路: 代码: public int MaxDepth(TreeNode root) { if (root == null) return 0; return Mathf.Max(Ma ...

  9. c#学习笔记03——委托和事件

    委托:一种引用类型,这种类型可以用来定义方法签名,从而使用委托实现将方法作为参数传递给其他方法.类似于C++中的函数之争,使用委托使程序员可以将方法引用封装在委托对象内. 定义和声明委托: deleg ...

  10. ZJNU 1217 - 航线问题——高级

    将所有航线的其中一边排序后,另一边进行类dp 定义一个数组c,c[i]表示在所有能够开通i条航线的组合中,位置序号最大的那条航线的序号的最小值 比如下面一个样例 1 3 2 4 3 1 4 2 此时对 ...