为什么要使用服务
1.在一个项目中不可避免的要在不同的component中使用同一份数据,普通的方式是将同样的代码在不同的地方复制粘贴,这样显然是不可取的。这时候我们可以定义一个数据服务,当我们需要它的时候只需要在相关组件中注入即可
2.服务对其调用者是透明的,使用服务可以让组件更加清洁,而且后期维护只需要修改服务就可以而不用在每一个使用数据的地方都修改
服务的用法
这里以官网demo为例
1.先在app文件夹中定义一个服务,服务的格式如下
import { Injectable } from '@angular/core';
@Injectable()
export class HeroService {
}
这里的注解标记是告诉angular可以将该服务所需要的一些依赖注入
2.向服务中添加方法
@Injectable()
export class HeroService {
getHeroes(): void {} // stub
}
服务的调用者并不知道我们从哪获取数据,我们可以从网络中获取,也可以从本地 获取,甚至是从模拟数据中获取,这里我们以模拟数据为例
3.模拟数据类
在app文件加下定义一个mock-heroes.ts文件,内容如下
import { Hero } from './hero';
export const HEROES: Hero[] = [
{id: 11, name: 'Mr. Nice'},
{id: 12, name: 'Narco'},
{id: 13, name: 'Bombasto'},
{id: 14, name: 'Celeritas'},
{id: 15, name: 'Magneta'},
{id: 16, name: 'RubberMan'},
{id: 17, name: 'Dynama'},
{id: 18, name: 'Dr IQ'},
{id: 19, name: 'Magma'},
{id: 20, name: 'Tornado'}
];
这里需要引入Hero类,因为在类中用到了这个类型,export是告诉angular这个类可以被其他类引用
4.方法的实现
import { Injectable } from '@angular/core';
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
@Injectable()
export class HeroService {
getHeroes(): Hero[] {
return HEROES;
}
}
这里ruturn 的就是模拟数据文件中定义的常量 HEROES
5.在组建中使用服务前的准备
首先需要告知angular这个服务,使用
import { HeroService } from './hero.service';
引入之后将服务注入组件中
constructor(private heroService: HeroService) { }
constructor中什么也没做,只是定义了一个私有的heroService变量,并将其作为
服务的注入点,但是注入机制并不知道具体应该怎样将服务,所以我们要在
@component块中告知注入方式
providers: [HeroService]
这样当创建一个组建的时候,providers数组就告知angular要创建一个服务实例,这样就可以使用服务中的成员了
6.使用服务
this.heroes = this.heroService.getHeroes();
这样就实现了数据从数据源向组建的流动
异步服务
上面使用的服务是同步的,因为数据在本地,所以不会感觉到请求数据的过程,但是当我们从远程服务器请求数据时,很可能因为各种原因导致数据无法请求到,这时候我们无法让浏览器一直等待,这样就用到了异步
在服务中用到了 Promise ,可以把它理解为一个约定,即 返回结果后调用反馈函数,这个结果可以是正确的结果也可以是错误的信息。
可以这样使用Promise
getHeroes(): Promise<Hero[]> {
return Promise.resolve(HEROES);
}
如此一来在调用时就可以
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
反馈函数将返回的数据赋值给组件中的变量