@angular前端项目代码优化之构建Api Tree的方法

在前端项目的开发过程中,往往后端会给到一份数据接口(本文简称api),为了减少后期的维护以及出错成本,我的考虑是希望能够找到这么一种方法,可以将所有的api以某种方式统一的管理起来,并且很方便的进行维护,比如当后端修改了api名,我可以很快的定位到该api进行修改,或者当后端添加了新的api,我可以很快的知道具体是一个api写漏了。

于是,我有了构建Api Tree的想法。

一、前后端分离(Resful api)

在前后端分离的开发模式中,前后端的交互点主要在于各个数据接口,也就是说后端把每个功能封装成了api,供前端调用。

举个例子,假设后端提供了关于user的以下3个api:

http(s)://www.xxx.com/api/v1/user/{ id } http(s)://www.xxx.com/api/v1/user/getByName/{ name } http(s)://www.xxx.com/api/v1/user/getByAge/{ age }

对应的api描述如下(为了方便理解,这里只考虑get请求):

1 获取用户id的用户数据
2 获取用户名为name的用户信息    
3 获取年龄为age的用户列表

二、在Component中调用api接口获取数据

目前各大前端框架比如angular、vue以及react等,都有提供相关HttpClient,用来发起http请求,比如get、post、put、delete等,由于本人比较熟悉angular,下面代码以angular进行举例(其他框架做法类似),代码统一使用typescript语法。

在app.component.ts中调用api:

import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { userInfo; constructor(private http: HttpClient) { this.getUserById(1); } async getUserById(userId) { const url = `https://www.xxx.com/api/v1/user/${userId}`; this.userInfo = await this.http.get(url).toPromise(); } }

三、封装UserHttpService

在项目中,由于多个页面可能需要调用同一个api,为了减少代码的冗余以及方便维护,比较好的方式是将所有的api封装到一个Service中,然后将这个Service实例化成单例模式,为所有的页面提供http服务。

angular提供了依赖注入的功能,可以将Service注入到Module中,并且在Module中的各个Component共享同一个Service,因此不需要手动去实现Service的单例模式。

代码如下:

user.http.service.ts

import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; const HOST_URL = `https://www.xxx.com/api/v1`; @Injectable() export class UserHttpService { constructor(private http: HttpClient) { } async getUserById(userId) { const url = `${HOST_URL}/user/${userId}`; return this.http.get(url).toPromise(); } async getUserByName(name) { const url = `${HOST_URL}/user/getByName/${name}`; return this.http.get(url).toPromise(); } async getUserByAge(age) { const url = `${HOST_URL}/user/getByAge/${age}`; return this.http.get(url).toPromise(); } }

app.component.ts

import { Component } from '@angular/core'; import { UserHttpService } from './user.http.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { constructor(private userHttpService: UserHttpService) { this.getUserById(1); } async getUserById(userId) { const userInfo = await this.userHttpService.getUserById(userId); console.log(userInfo); } async getUserByName(name) { const userInfo = await this.userHttpService.getUserByName(name); console.log(userInfo); } async getUserByAge(age) { const userInfoList = await this.userHttpService.getUserByAge(age); console.log(userInfoList); } }

这样的好处在于:

1、团队合作:

可以将前端项目分为HttpService层和Component层,由不同的人进行分开维护

2、减少代码的冗余:

在多个Component中调用同一个api时,不需要写多份代码

3、降低维护和扩展成本:

当后端增加或修改接口时,由于所有的user api都在UserHttpService里,所以能够很容易的进行接口调整,并且不影响Component层的代码

但以上方案还存在一个缺点,即url使用字符串拼接的形式:

const url = `${HOST_URL}/user/getByName/${name}`;

这样容易出现以下问题:

1、接口名拼接出错,并且由于是字符串拼接,不会有语法提示(ts)

2、没有一份完整的映射后端的api表,出现问题时,不容易排查 因此,接下来进入本文的主题:构建Api Tree。

四、手动构建Api Tree

什么是Api Tree呢,我把它定义为将所有的api以节点的形式挂在一个树上,最后形成了一棵包含所有api的树形结构。

对api tree的构建初步想法(手动构建)如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/157c0ee7148033df1d115e7ff82ffce9.html