在写Angular应用时,我们通常把与视图逻辑无关的公共代码片段写在service组件中,然后以依赖注入的方式进行使用. Angular service是惰性初始化的(Lazily instantiated),也就是说只有应用组件发现依赖某个service组件时才会实例化依赖的服务组件,angular服务是单例的, 我们可以联想到Spring MVC框架中的service组件。
AngularJS框架中已经提供很多可重用的service组件,例如$http, $scope, $rootScope等,我们将在后面的api详解中具体介绍这些内建的服务组件,内建的组件都以'$'符号开头,因此我们在实现自己的service组件时应当避免在service的名字中用‘$’字符作为前缀。
如何使用Service
只需在组件(controller, service, filter或者directive)的构造方法中声明所依赖的服务组件,Angular的依赖注入子系统便会自动注入服务组件。
让我们通过具体的代码来理解:
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 = []; } }; }]);
代码解析:
1. 在html模板中我们通过ng-app以及ng-controller绑定myServiceModule和MyController,在输入框中通过ng-model绑定message模型,并通过ng-init初始化message的值为“test”。
2. 通过ng-click给NOTIFY按钮添加了callNotify(message)的行为。
3. 在js代码中我们分别实现了MyController控制器和notify服务,notify服务通过factory的工厂方法来实现,依赖于$window服务,在构造函数的形参中声明“factory('notify', ['$window', function(win) {...”, 在MyController构造方法中添加了‘notify'依赖“controller('MyController', ['$scope','notify', function ($scope, notify)”,注意所声明的依赖的顺序必须与最后一个方法中的参数顺序保持一致,这样我们就可以在控制器中使用服务器组件了。
运行结果如图:
创建服务
Anguar应用开发者可以在模块中通过注册服务的名字和实现服务构造方法定义服务组件。服务工厂方法会生成单例或者代表服务的函数,并注入到依赖该服务的组件中。
注册服务
通过Module API注册服务。一般使用Module#factory api注册服务:
例如:
var myModule = angular.module('myModule', []); myModule.factory('serviceId', function() { var shinyNewServiceInstance; // factory function body that constructs shinyNewServiceInstance return shinyNewServiceInstance; });
这里我们通过facotry在'myModule'中实现了服务的构造方法,并没有实例化。
服务的依赖
服务组件也可以依赖其他组件,我们可以在factory的方法签名中声明服务所依赖的组件。我们将在后续章节中详细介绍angular的依赖注入原理。
让我们看如下两个服务的示例代码:
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); }); }]);
在上面两段代码中,我们实现了batchModule模块并分别实现了两个服务 batchLog和routeTemplateMonitor.
1. batchLog服务依赖angular自带的$interval和$log服务,同时用messageQueue实现了对消息的缓存,通过$interval服务周期性的打出日志。
2. routeTemplateMonitor服务依赖 $route, batchLog, $rootScope服务。
3. 这两个服务都是通过数组标记来声明依赖的。
4. 数组中依赖的顺序与工厂方法中的参数顺序需保持一致。
通过$provide注册服务
我们还可以通过$provide服务在模块的config方法中注册服务:
angular.module('myModule', []).config(['$provide', function($provide) { $provide.factory('serviceId', function() { var shinyNewServiceInstance; // factory function body that constructs shinyNewServiceInstance return shinyNewServiceInstance; }); }]);
这种方式主要用于单元测试。
单元测试
在这个例子中我们通过Jasmine框架来测试上述的notify服务.
var mock, notify; 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"]); });
相关推荐
NULL 博文链接:https://boyitech.iteye.com/blog/2167272
5. **扩展形式博弈**:用于描述具有多个阶段或步骤的博弈,每一步玩家可以选择不同的行动,最后的支付取决于整个路径的选择。 6. **子博弈完美纳什均衡**:在动态博弈中,如果每一子博弈的每个节点都存在纳什均衡,...
论文研究-不确定性下多目标博弈中弱Pareto-NS均衡的存在性.pdf, 在已知不确定参数变化范围的假设下, 研究了多目标博弈中弱Pareto-NS均衡点的存在性问题. 首先结合非合作...
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程...
### 博弈论专题知识点详解 #### 一、博弈论概览 博弈论,又称对策论,是现代数学的一个重要分支,主要研究在各种策略情况下,参与者如何做出决策以达到自身利益最大化。这一理论不仅在数学领域有广泛的应用,同时...
哈佛大学的博弈论讲义是这个领域的权威资料之一,深受学者和学生们的喜爱。本讲义深入浅出地介绍了博弈论的基本概念、理论与应用,帮助读者理解在竞争与合作中的决策制定。 首先,我们要理解博弈论的核心概念——...
讲义第三章详细讲解了子博弈精炼纳什均衡,这是一种动态博弈的解概念,要求均衡策略不仅要在初始阶段是最佳的,而且在任何可能的子博弈中也必须是最优的。以房地产开发项目的例子来说明,开发商A和B在面对不确定市场...
微观经济学讲义-第13章博弈论
在本讲义中,我们将探讨非合作博弈理论和信息经济学的相关概念。 首先,非合作博弈理论是博弈论的核心,主要关注参与者在没有共同利益或协议约束下的决策过程。在完全信息静态博弈中,所有参与者都掌握所有相关信息...
本讲义涵盖的内容广泛,包括了非合作博弈理论、完全信息与不完全信息博弈,以及信息经济学中的委托-代理理论和信号传递机制。 首先,非合作博弈理论是博弈论的基础,它假设参与者无法通过协议或合作改变博弈结果。...
2. **完全信息动态博弈** - 这部分涉及博弈的动态过程,我们将深入研究子博弈精炼纳什均衡,这是考虑到博弈的各个阶段,参与者如何在每个阶段做出最优决策。 3. **不完全信息静态博弈** - 在参与者掌握的信息不完全...
本讲义详细介绍了非合作博弈理论和信息经济学的相关概念。 首先,讲义涵盖了非合作博弈理论的基础,包括完全信息静态博弈。在完全信息静态博弈中,所有参与者都了解游戏的所有规则、支付矩阵和对手的策略。纳什均衡...
七所大学的博弈论讲义,包括哈佛大学.卡内基梅隆大学.芝加哥大学.加利福尼亚大学(圣. 迭戈校区).加利福尼亚
势博弈与时变Log-linear分布式拓扑控制算法 势博弈与时变Log-linear分布式拓扑控制算法是为了解决UWSNs(Underwater Wireless Sensor Networks,水下无线传感器网络)中网络拓扑控制不稳定、频繁变化引起的网络能耗...
2019年2季度大类资产配置报告:从基本面博弈转向资金面博弈-华泰证券-20190424.pdf
计算博弈第二讲-V61 计算博弈是自动化研究所 University of Chinese of Academy of Sciences 的一门专业普及课,旨在让学生理解博弈的基本概念、方法和应用。第二讲的主要内容是博弈表示方法、常见博弈类型和博弈的...
「安全管理」欧怀谷-安全服务化趋势下 资源博弈时代将至 - 安全管理 网络安全 WAF 身份管理 WAF 安全漏洞
人机博弈。PDF中文版。。。。。。。。。。。。。。。。。。。。。。。。。
博弈是什么意思-博弈之道须正矣.docx