点击查看AngularJS系列目录
转载请注明出处:http://www.cnblogs.com/leosx/


服务

Angular的服务也是使用依赖注入(dependency injection (DI))去获取相关对象的实例的。你可以在整个app当中,去共享你的代码。

Angular的服务有两点特性:

1、懒惰实例化 -- 只有当你依赖了它的时候,它才会被创建。

2、单例模式 -- 每一个依赖了它的组件只会创建一个实例。服务的创建是由服务工厂来创建的。

Angular官方提供了一些常用的服务(例如:$http),但是但部分app中,我们都会需要去创建属于自己的服务。

注意: Angular自己提供的服务或者核心对象,都是以$ 开头的(例如 $http) 也就是说在自定义服务的时候,最好不要以$开头。以免覆盖影响到了Angular自带的服务或功能。

使用服务

要使用Angular的服务,就得将它注入给需要它的组件(包括:指令directive、控制器controller、服务service、过滤器filter等)。具体如何操作,见下面例子:

第一个文件:index.html

<div id="simple" ng-controller="MyController">
<p>Let's try this simple notify service, injected into the controller...</p>
<input ng-init="message='test'" ng-model="message" >
<button ng-click="callNotify(message);">NOTIFY</button>
<p>(you have to click 3 times to see an alert)</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');
});

示例如下:

自定义服务

开发人员可以通过注册服务的名字实现服务的工厂方法(factory)来自定义服务。

服务会被服务工厂(factory)所创建,并且是对于一个调用组件来说,是单例的。然后再把这个实例注入到依赖这个服务的组件的构造函数中去。

注册服务

服务是使用Module factory(模块的factory方法) API去注册的。如下:

var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
var shinyNewServiceInstance;
// factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});

服务的依赖

服务也可以有自己的依赖。就像在一个控制器中声明依赖一样,我们同样可以通过在服务的工厂函数参数中指定它们所依赖其它组件。

关于更多和依赖相关的文档,点击这里(dependency injection)可以查看。

下面的例子中的module有着两个服务,每个服务都有着依赖组件的组件。

var batchModule = angular.module('batchModule', []);

/**
* The `batchLog` service allows for messages to be queued in memory and flushed
* to the console.log every 50 seconds.
*
* @param {*} message Message to be logged.
*/
batchModule.factory('batchLog', ['$interval', '$log', function($interval, $log) {
var messageQueue = []; function log() {
if (messageQueue.length) {
$log.log('batchLog messages: ', messageQueue);
messageQueue = [];
}
} // start periodic checking
$interval(log, 50000); return function(message) {
messageQueue.push(message);
}
}]); /**
* `routeTemplateMonitor` monitors each `$route` change and logs the current
* template via the `batchLog` service.
*/
batchModule.factory('routeTemplateMonitor', ['$route', 'batchLog', '$rootScope',
function($route, batchLog, $rootScope) {
$rootScope.$on('$routeChangeSuccess', function() {
batchLog($route.current ? $route.current.template : null);
});
}]);

在上面的例子中:

1、batchLog 服务依赖了Angular内置的$interval 服务和 $log 服务。

2、routeTemplateMonitor 服务依赖了Angular内置的 $route 服务和我们自定义的batchLog 服务。

3、这两种服务都使用数组表示法来声明它们的依赖。

4、注意,依赖声明的顺序就是构造函数中参数的顺序。

使用 $provide注册服务

你也可以使用模块的配置功能$provide去注册服务(自定义服务),如下:

angular.module('myModule', []).config(['$provide', function($provide) {
$provide.factory('serviceId', function() {
var shinyNewServiceInstance;
// factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
}]);

这种技术通常用于在单元测试中模拟出一个服务的依赖。

单元测试

下面是一个用于测试上面的例子创建的notify服务的单元测试。单元测试示例发出的告警是使用Jasmine spy 模拟出来的,而不是真正的浏览器发出的告警信息。

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.callCount).toEqual(2);
expect(mock.alert.mostRecentCall.args).toEqual(["more\ntwo\nthird"]);
});

AngularJS–service(服务)的更多相关文章

  1. 解决VMWARE NAT SERVICE服务无法启动或服务消失的问题

    解决VMWARE NAT SERVICE服务无法启动或服务消失的问题 2016-02-02 11:18 2012人阅读 评论(2) 收藏 举报  分类: 网络通信(3)  今日使用VMware中的Wi ...

  2. 使用axis开发web service服务端

    一.axis环境搭建 1.安装环境 JDK.Tomcat或Resin.eclipse等. 2.到 http://www.apache.org/dyn/closer.cgi/ws/axis/1_4下载A ...

  3. win7提示“User Profile Service服务未能登录”

    注:本文由Colin撰写,版权所有!转载请注明原文地址,谢谢合作! 最近,有个同事打电话告诉我说他的用户名无法登陆到系统,提示“User Profile Service服务未能登录,无法加载用户配置文 ...

  4. Android 通过JNI实现守护进程,使得Service服务不被杀死

    来自: http://finalshares.com/read-7306 转载请注明出处: http://blog.csdn.net/yyh352091626/article/details/5054 ...

  5. Service服务

    Android多线程: 定义线程的2种方式: 1.继承Thread类,重写run()方法,new一个实例,用start()方法启动:new MyThread().start(); 2.实现Runnab ...

  6. Centos6.5 设置Tomcat8 service服务实现自启动和服务管理

    Centos6.5 设置Tomcat8 service服务实现自启动和服务管理 将tomcat设置成像apache,nginx一样. 用serviec xxxx start/stop/restart ...

  7. Android 综合揭秘 —— 全面剖释 Service 服务

    引言 Service 服务是 Android 系统最常用的四大部件之一,Android 支持 Service 服务的原因主要目的有两个,一是简化后台任务的实现,二是实现在同一台设备当中跨进程的远程信息 ...

  8. win8.1 user profile service 服务登录失败

    在Win 8.1 上新建个用户后,不能登录. 出现 user profile service 服务登录失败. 无法加载用户配置文件. 网上大部分相同提示的问题是有关已有账号不能再次登陆的. 解决方式是 ...

  9. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

随机推荐

  1. Django 学习笔记(五)模板标签

    关于Django模板标签官方网址https://docs.djangoproject.com/en/1.11/ref/templates/builtins/ 1.IF标签 Hello World/vi ...

  2. Java-break,continue,return用法

    当年的我也算是基础小王子,但是长时间的不用导致我与他们越来越陌生了,所以我要把他们记在我的本本上. 首先我们要明白,java中到底有多少个循环关键字? 答:没错,就是3个,他们分别是:for(初始值: ...

  3. angular2 官方demo heroApp

    最近学习angular2,于是从官网的hero例子开始学习.经过几番周折终于完成了这个例子.收益匪浅.个人建议在开始学习例子前可以先了解一些概念,模块,组件,装饰器.....,有助于写代码时候的逻辑. ...

  4. Maven生成可以直接运行的jar包的多种方式

    Maven可以使用mvn package指令对项目进行打包,如果使用Java -jar xxx.jar执行运行jar文件,会出现"no main manifest attribute, in ...

  5. log4j使用和配置详解

    日志是应用软件中不可缺少的部分,Apache的开源项目Log4j是一个功能强大的日志组件,提供方便的日志记录.以下是个人经验,具体请参考Log4j文档指南. Log4j下载 在apache网站:htt ...

  6. 移动端踩坑之旅-ios下fixed、软键盘相关问题总结

    最近一个项目掉进了移动端的大坑,包括ios下fixed布局,h5唤起键盘等问题,作为一个B端程序员,弱项就是浏览器的兼容性和移动端的适配(毕竟我们可以要求使用chrome),还好这次让我学习了一下相关 ...

  7. chrome开发工具指南(十四)

    模拟和测试其他浏览器 您的任务不只局限于确保网站在 Chrome 和 Android 上出色运行.即使 Device Mode 可以模拟 iPhone 等多种其他设备,我们仍鼓励您查看其他浏览器模拟解 ...

  8. Spring中的线程池和定时任务功能

    1.功能介绍 Spring框架提供了线程池和定时任务执行的抽象接口:TaskExecutor和TaskScheduler来支持异步执行任务和定时执行任务功能.同时使用框架自己定义的抽象接口来屏蔽掉底层 ...

  9. 09 Linear Regression

    线性回归假设 错误衡量/代价函数---均方误差 最小化样本内代价函数 只有满秩方阵才有逆矩阵 线性回归算法 线性回归算法是隐式迭代的 线性回归算法泛化可能的保证 线性分类是近似求解,线性回归是解析求解 ...

  10. 【Alpha】Daily Scrum Meeting——Day5

    站立式会议照片 1.本次会议为第五次Meeting会议: 2.本次会议在上午大课间09:40,在陆大楼召开,本次会议为30分钟讨论昨天的任务完成情况以及接下来的任务安排. 燃尽图 每个人的工作分配 成 ...