新建Service
Service¶
通过Service和API进行交互,并将数据返回。
在libs下面建立文件夹名为:backend 用于存放和API交互的Service
1. 创建名为backend的module¶
1  | ng generate lib backend --tags=lib:backend --routing --lazy --unit-test-runner jest --parent-module=apps/client/src/app/app.module.ts  | 

2. 新建名为hr-manager的service文件¶
在 libs->backend->src->lib 文件夹上,右键选择:Open in Integrated Termial。
执行下记代码,创建service。
1  | ng generate service hr-manager/hr-manager  | 

3. 测试¶
接下来,开始编写关于用户的增删改查的service代码块。
3.1 改造结构体¶
之前在第一个程序中, 创建state的时候,生成了content-hrmanager.models.ts。我们需要在里面填写各个属性字段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  | /** * 用户结构体 */ export interface ContentHrmanagerEntity { /** * ID */ id: number; /** * 名称 */ name: string; /** * 年龄 */ age: number; }  | 
3.2 编写GET代码¶
打开刚才创建的HrManagerService文件。利用Angualar中HttpClient来进行代码编写。
1. 在BackendModule中引入:HttpClientModule

在app.module.ts中引入BackendMoudle

2. 在constructor中引入HttpClient

3. 手动引入ContentHrmanagerEntity
1  | import { ContentHrmanagerEntity } from '@redux-app/content/hrmanager';  | 
上记的 redux-app/content/hrmanager 在下记的tsconfig中查找。

4. 获取全部用户接口
1 2 3 4 5 6 7 8 9 10 11 12 13  | /** * mock服务器接口 */ private readonly API = 'http://localhost:3000/users'; /** * 获取user全部数据 */ public getAll(): Observable<ContentHrmanagerEntity[]> { return this.http.get(`${this.API}`).pipe( map(data => (data || [] ) as ContentHrmanagerEntity[]) ); }  | 
5. 将创建的HrManagerService导出

6. 在form.component.ts中,引入HrManagerSerivce
1  | import { HrManagerService } from '@redux-app/backend';  | 
引入方法和3类似,因为backend和content是作为libs的两个小模块,没有相互引用。所以需要收入引入相关的Entity、Service之类的。
在constructor中引用:
1  | constructor(private hrManagerService: HrManagerService) {}  | 
下面我们开始测试第一个实际交互的例子,通过点击“查询”按钮,获取所有用户信息,并在控制台显示出来。
因为我们需要利用rxjs操作符来将observable流的数据取出来,没有安装rxjs,按下记方式install。
1  | npm install rxjs  | 
在search查找方法中,我们填写下面的代码,之后按照下记的步骤查看运行结果
- 
用 json-server ./mock/_fixture/hr-manager.json 命令启动mock
 - 
运行client程序
 
1 2 3 4 5 6  | const users$ = this.hrManagerService.getAll(); users$.subscribe(data => { data.forEach(user => { console.log('id = ' + user.id + ' name = ' + user.name + ' age = ' + user.age); }) });  | 
在浏览器中,点击“查询”按钮,并在控制台查看结果。

虽然从控制台看到了运行的结果,但是我们没有测试错误的场景,下面 我们来改造一下代码。
- 在service代码块中,添加catchError来捕获异常
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  | // hr-manager.service.ts /** * 获取user全部数据 */ public getAll(): Observable<ContentHrmanagerEntity[]> { return this.http.get(`${this.API}`).pipe( map((data) => (data || []) as ContentHrmanagerEntity[]), catchError((err: HttpErrorResponse) => { if (err.status === 404) { return of(null); } return throwError(err); }) ); }  | 
- search方法中添加err函数进行处理
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  | /** * 查找 */ search() { const users$ = this.hrManagerService.getAll(); users$.subscribe(data => { if(data === null) { // 跳转到404页面 return; } data.forEach(user => { console.log('id = ' + user.id + ' name = ' + user.name + ' age = ' + user.age); }) }, err => { console.log((err as HttpErrorResponse).message); }); }  | 
- 
测试场景:
- 将mock服务器断开链接:
 
当点击“查询”按钮,在控制台输入errMessage

- 访问未知的接口
 
如: 将查询接口中的users换成users2

 
接下来,继续扩展get方法,根据id来查询用户数据。
- 在service代码中,添加下面方法
 
1 2 3 4 5 6  | /** * 获取指定id的user数据 */ public get(id: number): Observable<ContentHrmanagerEntity> { return this.http.get(`${this.API}/${id}`) as Observable<ContentHrmanagerEntity>; }  | 
- search方法改造
 
1 2 3 4 5 6 7 8 9 10 11 12  | /** * 查找 */ search() { const id = this.id.nativeElement.value; const user$ = this.hrManagerService.get(+id); user$.subscribe( user => console.log('id = ' + user.id + ' name = ' + user.name + ' age = ' + user.age), err => { console.log((err as HttpErrorResponse).message); }); }  | 
- 
测试场景
- id输入框中输入1
 

- id输入框输入users不存在的数据,如:5
 
