angular2系列教程(七)Injectable、Promise、Interface、使用服务
今天我们要讲的ng2的service这个概念,和ng1一样,service通常用于发送http请求,但其实你可以在里面封装任何你想封装的方法,有时候控制器之间的通讯也是依靠service来完成的,让我们一睹为快!
例子 例子是官方的例子,加载一个英雄列表,点击显示详细信息。我直接放在我们的升级后的装备里面。
文章图片
源代码
Injectable 在ng2里面如何编写服务呢?非常简单,你只需要写个类即可。那么这个@Injectable()是做什么的?其实单就这个例子来说,我们是不需要写个这个装饰的,因为我们的HeroSerivce没有依赖,如果你要写一个有依赖的服务,那么你需要加上这个@Injectable(),此处加上@Injectable()是可有可无的,但是写上是个好习惯。
app/hero.service.ts(部分代码)
文章图片
@Injectable() export class HeroService { getHeroes() { return Promise.resolve(HEROES); } // See the "Take it slow" appendix getHeroesSlowly() { return new Promise(resolve => setTimeout(() => resolve(HEROES), 2000) // 2 seconds ); } }
文章图片
以上代码我们干了哪些事儿呢?
- 写了一个使用injectable装饰的类
- 写了两个成员函数
- 一个返回一个Promise,直接resolve数据
- 另一个也返回一个Promise,不过在两秒后resolve数据
Promise 如果你玩过ng1,你一定对promise不陌生,因为我们经常在路由里面写resolve,这里就可以接受一个Promise对象。还有ng1中的$q.defer()等等。
但是promise并不是ng1的专利,你可以在你的任何javascript程序中使用promise,因为在ES6中已经原生提供Promise对象。你可以查看它的用法,这里我简单描述下:
- 构造Promise,只需要在里面加入一个参数,这个参数是个function,这个function可以接受两个参数:resolve, reject。或者使用Promise.resolve(),不过这样没有延迟了。
- 使用Promise对象,最常用的方法是then(),里面接受一个function,这个function的参数为resolve的值。除了then()还有catch()等
文章图片
- 输入Promise,是个function。
- 输入Promise.resolve('123'),我们得到一个状态为“已经解决”的promise。
- 输入new Promise(resolve=>resolve('123')),我们还是得到一个状态为“已经解决”的promise。
然后让我们来看Promise的then方法:
文章图片
- 首先我们写了一个已经resolved的promise,并将其赋值给p
- 然后使用p.then(),在回调函数里面打印参数,得到‘123’
- 最后p.then()整体返回的是个初始化(pending)的promise。
app/hero.service.ts(部分代码)
文章图片
@Injectable() export class HeroService { getHeroes() { return Promise.resolve(HEROES); } // See the "Take it slow" appendix getHeroesSlowly() { return new Promise(resolve => setTimeout(() => resolve(HEROES), 2000) // 2 seconds); } }
文章图片
那么我们为何要使用promise呢?主要是为了解决回调地狱的问题。因为有了promise,你不必再写深层的回调,而是像极了同步的写法。
这是我的一个ng1的项目的部分代码,用promise的then()来解决回调地狱。
文章图片
Auth.$createUser({email: email, password: pass}) .then(function() { // authenticate so we have permission to write to Firebase return Auth.$authWithPassword({ email: email, password: pass }); }) .then(function(user) { // create a user profile in our data store var ref = wdutil.ref('users', user.uid); return wdutil.handler(function(cb) { ref.set({email: email, name: $scope.name||firstPartOfEmail(email)}, cb); }); }) .then(function(/* user */) { $scope.wait.show=false; // redirect to the account page $location.path('/account'); }, function(err) { $scope.wait.show=false; $scope.alerts.push({type:'danger',msg:wdutil.errMessage(err)}); });
文章图片
Interface 在编写这个服务的过程中我们使用了interface这个概念,这个知识点属于ts的范畴,我们通常在接口中声明类型,有点像react中的propTypes:
app/hero.ts
export interface Hero { id: number; name: string; }
然后我们在我们的服务中使用了这个接口:
app/hero.service.ts(部分代码)
import {Hero} from './hero';
app/hero.service.ts(部分代码)
return new Promise(resolve => setTimeout(() => resolve(HEROES), 2000) // 2 seconds );
除此之外,我们在我们的组件里面也多次使用了这个接口:
app/app.component.ts
heroes: Hero[]; selectedHero: Hero;
app/hero-detail.component.ts
export class HeroDetailComponent { hero: Hero; }
到此为止,我们的服务就算是写好了!
使用服务 让我们在组件中测试一下我们写好的服务吧:
app/app.component.ts(部分代码)
import {HeroService} from './hero.service';
app/app.component.ts(部分代码)
providers: [HeroService]
app/app.component.ts(部分代码)
文章图片
constructor(private _heroService: HeroService) { }getHeroes() { this._heroService.getHeroes().then(heroes => this.heroes = heroes); }
文章图片
以上代码我们干了这些事儿:
- 利用模块系统导入这个服务类
- 在组件中注入这个服务
- 在构造函数中将这个服务赋给一个私有变量_heroService
- 然后就可以尽情地在类中使用这个服务对象了this._heroService
推荐阅读
- 2.6|2.6 Photoshop操作步骤的撤消和重做 [Ps教程]
- 【欢喜是你·三宅系列①】⑶
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- angular2内置管道
- 你不可不知的真相系列之科学
- 人脸识别|【人脸识别系列】| 实现自动化妆
- 2018-06-13金句系列7(金句结构-改编古现代诗词)
- Unity和Android通信系列文章2——扩展UnityPlayerActivity
- 乡野村趣系列之烧仙草
- Java内存泄漏分析系列之二(jstack生成的Thread|Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析)