AngularJS in Action读书笔记3——走近Services
试着想想这些问题:如果一个controller只关心自己所控制的view页面,那么对于整个application来说,你如何调用想要的function;如果controller从来都不会和其他controller通讯,那controller之间又是如何实现数据共享。有问题,就有解决方案,本章主要讲解如何创建一个简单的service并如何使用它和远端的server通讯。
什么是models和services
hello,service
什么是services,从技术层面来说,angularjs中的service就是抽取的一些公用的功能函数封装起来可以在整个应用中调用。换句话说,service是一种可以和远端其他service通讯的机制,而model不仅仅具备这套机制,还负责管理服务里面的数据。
Angularjs中的service表现形式很丰富,但是归根结底都是通过对于内置服务$provide的不同程度的封装。一般我们将其定义在angular.module中,表现形式有module.value, module.constant, module.service, module.factory还有module.provider。
本章节主要就来谈谈如何创建一个可以定义story类型的service,并且可以在StoryboardCtrl中调用。在Angello.js中,我们注册一个service形式的value,即myModule.value,将其命名为STORY_TYPES,然后在第二个参数中传入我们要定义的数据,代码如下:
这样我们就可以通过依赖注入的方式注入STORY_TYPES,从而在整个angello应用中使用。好比StoryboardController.js:
这里我们注入STORY_TYPES,然后就可以将其赋值给myStory,从而在前台界面展示。这种service的定义形式的优雅之处就在于,定义好了service后,可以在不同的controller、directive乃至service中调用。
service的生命周期
- 首先在angular.module定义service;
- 在compilation阶段,service在完成实例创建,并注册到工厂类上;
- 当需要调用这个service时,$inject服务就会在缓存上在查找有没有这个服务。如果缓存上有,那么$inject就会从缓存上取出这个service的实例完成注入;否则,$inject服务就会请求工厂类为其重新创建一个service并返回这个service的实例以供调用。
注意:service采用的是懒加载模式,只有被调用的时候,才会被加载进来。同时还是单例模式,其只初始化一次,然后在application的任何地方调用的是同一个实例。
service的类型
总共有5种形式定义service,他们之间的区别以及使用的场景见下图:
- module.value——用于存储一些简单变量,并且在运行时可能需要改变的变量
- module.constant——用于存储一些不会改变的变量
- module.service——通过构造方法创建service,该种形式对于熟悉面向对象的开发者更容易接受,该service中还包含this关键字,用于对外暴露方法
- module.factory——通过构造函数创建service,直接在这个创建的对象上添加属性方法,然后返回即可
- module.provider——用于需要对service进行修改并与可以与application的configure通讯联系的情况。
value service
value service是最简单的一种service,其共有两个参数,第一个参数是service的名字,第二个参数是具体的数据可以是一个值、对象、函数。
value形式的service是不能够在module.config中访问的。
constant service
constant service与value service很像,唯一的不同就是constant可以被module.config访问并且定义的值不会改变。
service和factory
最常见的service就是service和factory,鉴于这两种service很像,所以放在一起说。
当通过module.service定义一个service,则返回的是构造函数构造出的实例。这对熟悉面向对象的开发人员是轻车熟路了。
前面的代码中,我们定义了一个名为LoadingService的service,我们可以将具有上下文的this对象赋值给了service变量。
下面我们来创建一个module.factory形式的LoadingService,这个和上面的差不多,只是它返回的是一个暴露了属性和方法的对象,外面可以访问这个对象的属性和方法。
provider service
provider是定义一个service的最底层方法。一般来说,我们不会直接定义module.provider,除非你需要添加一些额外的配置参数。在angello应用的代码中我们没有直接使用这个module.provider,但是将在$http interceptors和service decrators中配置内置provider。
Models with $http
应用尤其是web应用,从来都不是不是平白无故存在的。所以我们将会从探讨service到认识model,因为我们需要一种在客户端持久化数据并能与远端通讯的方式。angularjs能够很容易做到服务端和内置服务$http高效方便的通讯。
What is $http
$http是angularjs提供的service,可以基于http协议,使用浏览器的XMLHttpRequest对象或者JSONP实现远端通讯。服务端采用的是异步通讯模式,而$http是基于$q服务的deferred/promise模式。
Create your first model
我们将要创建第一个model——StoriesModel,用于请求远端并获取属于登陆者名下的stories。
首先我们需要在Angello.common模块下定义一个StoriesModel,并注入三个依赖服务——$http,AuthModel和ENDPOINT_URI,这些参数都是用于与远端通讯。$http承担主要的通讯功能,AuthModel和ENDPOINT_URI辅助构建调用的URI地址。
angular.module('Angello.Common')
.service('StoriesModel',
function ($http, EndpointConfigService, UtilsService) {
var service = this,
MODEL = '/stories/'; service.all = function () {
return $http.get(EndpointConfigService.getUrl(
MODEL + EndpointConfigService.getCurrentFormat()))
.then(
function(result) {
return UtilsService.objectToArray(result);
}
);
}; service.fetch = function (story_id) {
return $http.get(
EndpointConfigService.getUrlForId(MODEL, story_id)
);
}; service.create = function (story) {
return $http.post(
EndpointConfigService.getUrl(MODEL + EndpointConfigService.getCurrentFormat()), story
);
}; service.update = function (story_id, story) {
return $http.put(
EndpointConfigService.getUrlForId(MODEL, story_id), story
);
}; service.destroy = function (story_id) {
return $http.delete(
EndpointConfigService.getUrlForId(MODEL, story_id)
);
};
});
首先还是老一套将this赋值给一个变量service,然后将一个字符串赋值给变量MODEL以便后面构建合适的URI。
代码中定义了一个请求方法,用于获取登录者名下所有的stories。$http服务是基于REST状态协议的,所以可以通过$http.get(YOUR_URI)的方法来请求数据。而这里的URI又是通过EndpointConfigService来实现的。
至于前面所说的$http是异步请求,我们可能是看不到的,但是我们可以通过看StoryboardCtrl中的代码来了解异步请求的处理思想。
当getStories执行的时候,StoriesModel.all就会通过call请求,然后将得到的数据在then中完成处理,then函数中的参数就是请求到的数据。
$http一些使用的方法
你已经看到上面的例子是和通过GET请求来获取用户想要的stories。当然这只是其中一方面,我们还会需要知道如何得到某个指定user下的stories、如何创建一个stories以及如何更新、删除等。
谈到上面的这些问题,我们不得不服使用基于RESTful的$http与生俱来的一些方法和思想是多么的方便。你可以利用RESTful的特性几乎完成你所想要的一切操作:
Promises
我们来简短的认识下什么是promises。提到promises就不能不说异步请求,相对于同步请求来说,异步对于资源的使用更加充分,当然对于调试可能也更加麻烦点。关于同步与异步的实际场景的理解,请点击这里
与此同时,结合Angello这个application的代码来加深对promises的理解,让我们回到StoriesModel上,通过service.all来获取登录用户的stories
这个service.all返回的就是$http.get,我们将其视为一个promises对象。
然后在StoryboardController.js中的then方法中接收前面promises返回的值。这里的then接收三个参数——成功回调、错误回调以及状态变化回调。成功回调意味着promise成功返回,错误回调意味着promise返回失败,还有一个当遇到一些状态如长计算等,就会进入第三种状态notify,来给promise一个监听从而更新状态。
值得注意的是,在Angularjs1.3中引入了.then().catch().finally()来替代了前面的三种状态,当然了,选择哪种形式取决于个人的习惯。
下面还是借助service.all函数看看代码逻辑以及每行代码的含义:
至此,我们啃完了第四章,大概内容有:
- Services是一种定义共用的功能模块,以便在整个应用的任何地方使用的组件
- Services有五种不同的表现形式module.constant, module.value, module.service, module.factory, module.provider,各种形式尤其自身的特点以及适用场合
- $http与远端通讯很方便,因为其遵从RESTful请求协议
- $http基于deffered/promise API并且实现了异步请求机制
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。
友情赞助
如果你觉得博主的文章对你那么一点小帮助,恰巧你又有想打赏博主的小冲动,那么事不宜迟,赶紧扫一扫,小额地赞助下,攒个奶粉钱,也是让博主有动力继续努力,写出更好的文章^^。
1. 支付宝 2. 微信
首先我们需要在Angello.common模块下定义一个StoriesModel,并注入三个依赖服务——$http,AuthModel和ENDPOINT_URI,这些参数都是用于与远端通讯。$http承担主要的通讯功能,AuthModel和ENDPOINT_URI辅助构建调用的URI地址。
AngularJS in Action读书笔记3——走近Services的更多相关文章
- AngularJS in Action读书笔记6(实战篇)——bug hunting
这一系列文章感觉写的不好,思维跨度很大,原本是由于与<Angularjs in action>有种相见恨晚而激发要写点读后感之类的文章,但是在翻译或是阐述的时候还是会心有余而力不足,零零总 ...
- AngularJS in Action读书笔记2——view和controller的那些事儿
今天我们来818<angularjs in action>的第三章controller和view. 1.Big Picture概览图 View是angularjs编译html后呈现出来的, ...
- AngularJS in Action读书笔记4(实战篇)——创建Statistic模块
个人感觉<Angularjs in action>这本书写的很好,很流畅,循序渐进,深入浅出,关键是结合了一个托管于Github上的实例讲解的,有代码可查,对于初学者应该是个不错的途径.( ...
- AngularJS in Action读书笔记1——扫平一揽子专业术语
前(fei)言(hua): 数月前,以一个盲人摸象的姿态看了一些关于AngularJS的视频书籍,留下了我个人的一点或许是指点迷津或许是误人子弟的读后感.自以为已经达到熟悉ng的程度,但是因为刚入公司 ...
- AngularJS in Action读书笔记5(实战篇)——在directive中引入D3饼状图显示
前言: "宁肯像种子一样等待 也不愿像疲惫的陀螺 旋转得那样勉强" 这是前几天在查资料无意间看到的一位园友的签名,看完后又读了两遍,觉得很有味道.后来一寻根究底才知这是出资大诗 ...
- AngularJS高级程序设计读书笔记 -- 指令篇 之 内置指令
1. 内置指令(10-12 章) AngularJS 内置超过 50 个内置指令, 包括 数据绑定,表单验证,模板生成,时间处理 和 HTML 操作. 指令暴露了 AngularJS 的核心功能, 如 ...
- AngularJS高级程序设计读书笔记 -- 模块篇
一. 模块基础 1. 创建模块 <!DOCTYPE html> <html ng-app="exampleApp"> <head> <ti ...
- AngularJS高级程序设计读书笔记 -- 大纲篇
零. 初衷 现在 AngularJS 4 已经发布了, 楼主还停留在 1.x 的阶段, 深感自卑. 学习 AngularJS 的初衷是因为, 去年楼主开始尝试使用 Flask 开发自动化程序, 需要用 ...
- AngularJS高级程序设计读书笔记 -- 服务篇
服务是提供在整个应用程序中所使用的任何功能的单例对象. 单例 : 只用一个对象实例会被 AngularJS 创建出来, 并被程序需要服务的各个不同部分所共享. 1. 内置服务 一些关键方法也被 Ang ...
随机推荐
- ansible 自动化(2)
模块介绍: copy模块 使用copy模块,可以将本地文件一键复制到远程服务器:-a后跟上参数,参数中指定本地文件和远端路径: [root@ZABBIX ~]# ansible glq -m copy ...
- [OLE DB 源 [1]] 警告: 无法从 OLE DB 访问接口检索列代码页信息。如果该组件支持“DefaultCodePage”属性,将使用来自该属性的代码页。如果当前的字符串代码页值不正确,请更改该属性的值。如果该组件不支持该属性,将使用来自该组件的区域设置 ID 的代码页。
SSIS的警告信息,虽然不影响使用,但是对于一个有强迫症的人来说,实在痛苦, 解决办法:控件右键--属性--AlaywayseUseDefaultCodePage 修改成True即可,默认为False
- hadoop rpc基础
第一部分: hadoop rpc基础 RPC,远程程序调用,分布式计算中C/S模型的一个应用实例. 同其他RPC框架一样,Hadoop分为四个部分: 序列化层:支持多种框架实现序列化与反序列化 函数调 ...
- npm穿墙
GWF 很给力,很多东西都能墙掉,但是把 npm 也纳入黑名单,不知道 GWFer 是怎么想的.FQ翻了好多年了,原理其实也挺简单的,proxy 嘛! » 方法一 A) 国内源,http://cnpm ...
- 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- java提高篇(十八)-----数组之一:认识JAVA数组
噢,它明白了,河水既没有牛伯伯说的那么浅,也没有小松鼠说的那么深,只有自己亲自试过才知道!道听途说永远只能看到表明现象,只有亲自试过了,才知道它的深浅!!!!! 一.什么是数组 ...
- java笔试题(金山网络)
今天参加金山的校园招聘,java笔试,回来仔细研究实现一下: 题目1:工厂两条生产线,三个工人,生产线上可以最多存放m个产品,当生产线满时,机器停止生产,等产品线不满时才继续生产,每条产线上一次只能允 ...
- Unity3d热更新全书-加载(一)从AssetBundle说起
Unity3D动态下载资源,有没有解?有,AssetBundle就是通用解,任何一本书都会花大幅篇章来介绍AssetBundle. 我们也来说说AssetBundle 我们试全面的分析一下Unity3 ...
- [stm32] NRF24L01+USART搞定有线和无线通信
前言 一般进行远程监控时,2.4G无线通信是充当远程数据传输的一种方法.这时就需要在现场部分具备无线数据发送装置,而在上位机部分由于一般只有串口,所以将采集到的数据送到电脑里又要在上位机端设计一个数据 ...
- HTML5打造的炫酷本地音乐播放器-喵喵Player
将之前捣腾的音乐频谱效果加上一个播放列表就成了现在的喵喵播放器(Meow meow Player,额知道这名字很二很装萌~),全HTML5打造的网页程序,可本地运行也可以挂服务器上用. 在线Demo及 ...