点击查看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. 匿名委托与Lambda表达式

    通过使用匿名委托(匿名方法),使编程变得更加灵活,有关委托与匿名委托请参考我的前一篇Blog<委托与匿名委托>. 继续之前示例,代码如下: static void Main(string[ ...

  2. Android studio 安装的安装一些问题

    在国内如何更新android sdk? 由于众所周知的某些原因,我们无法直接连接android sdk的更新服务更新sdk,所以可以通过国内的ftp站点把常用的sdk组件如android platfo ...

  3. 16汇编第十讲完结Call变为函数以及指令的最后讲解

    16汇编完结Call变为函数以及指令的最后讲解 学了10天的16位汇编,这一讲就结束了,这里总结一下昨天的LOOP指令的缺陷,因为lOOP指令的缺陷,所以我们都改为下面的汇编代码使用了,自己去写,其中 ...

  4. Java内存模型:volatile详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt202 Java内存模型:volatile是干什么用的Volatile字段是用 ...

  5. SQL 软解析和硬解析详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt329 当客户端进程,将SQL语句通过监听器发送到Oracle时, 会触发一个 ...

  6. RMI,RPC,SOAP对比分析

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp60   1.RMI     使用java的程序员,对于RMI(Remot ...

  7. JUnit 3.8.1 源码学习

    JUnit 3.8.1 源码学习 环境搭建(源码加载配置) 由于IDE自身含有JUint插件,因此通过正常途径是没有源码加载入口的,因此需通过手动加载扩展JAR,然后再添加对应源码JAR,如图:项目右 ...

  8. 201521123060 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2. 书面作业 1.clone方法 1.1 Object对 ...

  9. 201521123054 《Java程序设计》第5周学习总结

    1. 本周学习总结 2. 书面作业 作业参考文件下载 代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出 ...

  10. 201521123052《Java程序设计》第1周学习总结

    1. 本周学习总结 1.认识Java,了解JVM.JRE与JDK,并下载与安装JDK: 2.设置好eclipse并使用eclipse完成简单的Java编程: 3.使用博客.码云与PTA,这些对Java ...