新建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
