服务
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. Angular开发者指南(七)依赖注入

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

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

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

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

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

  4. 手把手教你成为荣耀开发者:商户服务开通指南

    荣耀开发者服务平台是荣耀面向开发者的统一生态入口,通过聚合周边内外部系统,分全球多站点部署,为全球开发者提供业务全生命周期的商业支撑服务,拥有应用分发.智慧服务.开放能力.HONOR Connect等 ...

  5. 【翻新重写】WWDC 后苹果最新 App Store 审核条款!「内附最新开发者指南」

    WWDC 2016 大会之后,苹果公司发布了四个全新平台:iOS,macOS,watchOS 和 tvOS.并且在此之后,苹果应用商店审核条款也同时进行了更新--貌似不算进行了更新,简直就是重写!上个 ...

  6. google ProtoBuf开发者指南

    目录 1   概览 1.1   什么是protocol buffer 1.2   他们如何工作 1.3   为什么不用XML? 1.4   听起来像是为我的解决方案,如何开始? 1.5   一点历史 ...

  7. Android开发者指南(4) —— Application Fundamentals

    前言 本章内容为开发者指南(Dev Guide)/Framework Topics/Application Fundamentals,版本为Android2.3 r1,翻译转载并整理自译言:" ...

  8. Spring Security OAuth 2开发者指南译

    Spring Security OAuth 2开发者指南译 介绍 这是用户指南的支持OAuth 2.0.对于OAuth 1.0,一切都是不同的,所以看到它的用户指南. 本用户指南分为两部分,第一部分为 ...

  9. ProtoBuf开发者指南

    转载:http://www.cnblogs.com/foxhengxing/archive/2010/08/10/1796165.html google ProtoBuf开发者指南 ProtoBuf开 ...

最新文章

  1. 解决SqlServer2008修改表后保存时出现“save changes is not permitted…”问题
  2. [转] Deep Learning(深度学习)学习笔记整理系列
  3. 使用insert向表中添加数据MySQL_使用INSERT语句向表中插入数据(MSSQLSERVER版)
  4. Python6种创建字典的方式
  5. 国内物联网平台初探(七) ——Ablecloud物联网自助开发和大数据云平台
  6. Spring Ioc源码分析 之 Bean的加载(7):初始化
  7. 【Boost】boost库中thread多线程详解5——谈谈线程中断
  8. scala中何时使用下划线_在Scala中使用下划线
  9. mysql 8.0 一条insert语句的具体执行流程分析(一)
  10. oracle u01目录 100,文件目录空间利用率达到100%而导致数据库异常挂起的故障处理过...
  11. (35)FPGA打两拍、打三拍设计(第7天)
  12. Python对象引用和del删除引用
  13. 08 内存分配和程序内存布局
  14. MDC功能软件-归控算法介绍
  15. 数据结构与算法总结(八股文)
  16. 一步步学习SPD2010--第十四章节--在Web页面使用控件(2)--使用标准ASP.NET服务器控件...
  17. multisim二极管_每日干货——光敏二极管传感器
  18. windows系统下ink!canvas-node安装
  19. mysql group top_Mysql group by 后取 top N 问题
  20. 图解LeetCode06:Z字形变换

热门文章

  1. 车提示检测轮胎气压_无钥匙启动的车启动后,车主带着钥匙离开车,能不能把车开走?...
  2. 微信小程序swiper图片尺寸_微信小程序之swiper轮播图中的图片自适应高度的方法...
  3. 学习MSCKF笔记——前端、图像金字塔光流、Two Point Ransac
  4. 深蓝学院《从零开始手写VIO》作业四
  5. Large Kernel Matters
  6. 【赠书】深入浅出embedding:原理解析与应用实践
  7. 全球及中国生物识别车辆访问技术行业十四五应用现状及未来展望规划报告2022-2027年
  8. 使用Signature Tool自动生成P/Invoke调用Windows API的C#函数声明
  9. 32位的cpu不能安装linux_Python3.5.2 安装教程【64位/32位】
  10. 一个故事讲清楚BIO NIO 异步