前言(为何做)
过去的一段时间,我都认为 接口请求 封装是前端的必修课。 只要是写过生产环境前端代码的人,应该都脱离不了异步接口请求,那么 接口请求 的 封装 是必经之路。
直到前些天,我们屋某个美团写后台的小姑娘问我前端问题时。我才发现她们代码中的 接口请求 ,都是没有任何的封装,直接采用以下方式进行:
axios.post(`/api/xxxx/xxxx?xxx=${xxx}`, { ...data })
.then((result) => {if (result.errno) {....} else {....}
})
.catch((err) => {....
})
这样写也不是说不好,在某种程度上,这增加了代码的可读性。但是我们大多数页面需要的接口都不止一个,那么我们的组件中极有可能出现 数十上百 行重复代码。
那么随着请求的体量越来越大,我们的项目便越来越难以维护。
效果演示
const [e, r] = await api.getUserInfo(userid)
if (!e && r) this.userInfo = r.data.userinfo
上面是我们最终的实现效果。
接下来,我将带大家一步一步封装一套属于我们自己的 接口请求工具 ,同时也希望大家分享更好的思路。
注:
- 如果你希望直接看源码,请翻到 《完整代码》
- 这里以
axios
作示范,同样换成fetch
、 小程序的request
都是可以的- 我将会采用
typeScript
书写这段教程,如果你不需要,忽略掉对应的类型即可
思路清晰,先说分析(做什么)
在我们正式开发前,首先需要清楚请求一个接口都做了什么。
为此,消耗了两个小时时间,做了一个请求流程图,以便于我们后续进行需求分析(小声bb:Processon真难用 😢)
有了一个清晰的请求流程图,我们便可以区分出来两块重要的内容来进行拆分: 基础请求流程 、 拦截器 。
接下来我们将两块儿内容展开讲。
基础请求流程
基础请求流程,我们大致可以分为三块, 一是 请求进入请求拦截前 、二是 真正发起的请求 、三是 请求从响应拦截出来后 。
这其中可以归为两类,一类是 针对单独接口的处理二类是 针对所有接口需要的内容
- 针对单独接口的处理* 请求前的参数处理* 请求后的返回值处理
- 针对所有接口的处理* Post* Get* Put* Del
拦截器
拦截器,我们大致可以分为两类, 一类是 请求接口前的统一处理(请求拦截) 、 一类是 请求接口后的统一处理(响应拦截)
- 请求拦截* 请求调整* 用户标识
- 响应拦截* 网络错误处理* 授权错误处理* 普通错误处理* 代码异常处理
统一调用
随着我们的 Api
越来越多,我们可能需要给他们不同的分类,但我们并不希望每次调用都从不同的文件夹引入不同的 Api
,因此在 基础请求 + 拦截器 之外,我们还需要一个封包操作。
开发顺序
随着我们要做的内容越来越多,我们希望它有一个顺序以便于我们按部就班的开发(相信大家对开发中出现的不确定性都深恶痛绝)。以便于我们按照流程,无意外、无惊喜 的完成此次封装。
在我们的开发中,我们基本要遵循先处理通用内容在处理个性化内容的逻辑:
1.针对所有接口的处理(Get)
2.请求拦截
3.响应拦截
4.针对单独接口的处理
5.封包处理
6.针对所有接口的处理(Post、Put、Del)
tips
💡 这里大家可能意外为什么 Post、P