前言(为何做)
过去的一段时间,我都认为 接口请求 封装是前端的必修课。只要是写过生产环境前端代码的人,应该都脱离不了异步接口请求,那么 接口请求 的 封装 是必经之路。
直到前些天,我们屋某个美团写后台的小姑娘问我前端问题时。我才发现她们代码中的 接口请求 ,都是没有任何的封装,直接采用以下方式进行:
这样写也不是说不好,在某种程度上,这增加了代码的可读性。 但是我们大多数页面需要的接口都不止一个,那么我们的组件中极有可能出现 数十上百 行重复代码。
那么随着请求的体量越来越大,我们的项目便越来越难以维护。
效果演示
上面是我们最终的实现效果。
接下来,我将带大家一步一步封装一套属于我们自己的 接口请求工具 ,同时也希望大
家分享更好的思路。
- 如果你希望直接看源码,请翻到 《完整代码》
- 这里以
axios
作示范,同样换成 fetch
、 小程序的 request
都是可以的
- 我将会采用
typeScript
书写这段教程,如果你不需要,忽略掉对应的类型即可
思路清晰,先说分析(做什么)
在我们正式开发前,首先需要清楚请求一个接口都做了什么。
为此,消耗了两个小时时间,做了一个请求流程图,以便于我们后续进行需求分析(小声bb:Processon真难用 😢)
有了一个清晰的请求流程图,我们便可以区分出来两块重要的内容来进行拆分:基础请求流程 、 拦截器 。
接下来我们将两块儿内容展开讲。
基础请求流程
基础请求流程,我们大致可以分为三块, 一是 请求进入请求拦截前 、二是 真正发起的请求 、三是 请求从响应拦截出来后 。
这其中可以归为两类, 一类是 针对单独接口的处理 二类是 针对所有接口需要的内容
拦截器
拦截器,我们大致可以分为两类, 一类是 请求接口前的统一处理(请求拦截) 、 一类是 请求接口后的统一处理(响应拦截)
- 请求拦截
- 响应拦截
- 网络错误处理
- 授权错误处理
- 普通错误处理
- 代码异常处理
统一调用
随着我们的 Api
越来越多,我们可能需要给他们不同的分类,但我们并不希望每次调用都从不同的文件夹引入不同的 Api
,因此在 基础请求 + 拦截器 之外,我们还需要一个封包操作。
开发顺序
随着我们要做的内容越来越多,我们希望它有一个顺序以便于我们按部就班的开发(相信大家对开发中出现的不确定性都深恶痛绝)。 以便于我们按照流程,无意外、无惊喜 的完成此次封装。
在我们的开发中,我们基本要遵循先处理通用内容在处理个性化内容的逻辑:
- 针对所有接口的处理(Get)
- 请求拦截
- 响应拦截
- 针对单独接口的处理
- 封包处理
- 针对所有接口的处理(Post、Put、Del)
tips
💡 这里大家可能意外为什么 Post、Put、Del 的处理在最后开发:因为大多数情况,我们开发中希望所编写的内容有一个及时的回馈。
举个栗子:我在生活中发现 → 我们学习吉他时,大多数人半途而废了。但坚持下来的人基本无一例外的通过吉他在不同的阶段都获得了好处,包括但不限于 异性 的夸奖、舍友的鼓掌、 get女朋友 。这也是我们在毕业独处后,很难学会弹吉他的原因(无处炫耀)。
因此,我们需要让所开发的内容尽快达到可用的阶段(MVP)。
万事俱备、只欠东风(怎么做)
按照我们之前定好的顺序,按部就班的开发⑧!
针对所有接口的处理(Get)
我们希望以 const [e, r] = await api.getUserInfo(id)
的方式调用,代表着我们需要保证返回值稳定的返回 [err, result]
,所以我们需要在请求无论成功失败时,都以 resolve
方式调用。
同时,我们希望我们可以处理返回值,因此在这里封装了 clearFn
的回调函数。
请求拦截
请求拦截中,我们需要两块内容,一是 请求的调整 ,二是 配置用户标识
响应拦截
响应错误由三类错误组成:
因此,要优雅的处理响应拦截,我们必须先将三类错误函数写好,以便于我们增强代码扩展性及后期维护。
错误处理函数
适配
当我们将所有的错误类型处理函数写完,在 axios
的拦截器中进行调用即可。
针对单独接口的处理
基于上面的几类通用处理,我们这个请求的封装基本已经可用了。
但是我们还有一些额外的操作无处存放(参数处理、返回值处理),且我们并不想将他们耦合在页面中每次调用进行处理,那么我们显然需要一个位置来处理这些内容。
封包处理
接口分类封包
用户数据:api/path/user.ts
订单数据:api/path/shoporder.ts
调用点统一
api/index.ts
针对所有接口的处理(Post、Put、Del)
完整代码
业务处理函数:src/api/tool.ts
通用操作封装:src/api/server.ts
统一调用点:src/api/index.ts
接口:src/api/path/user.ts
| src/api/path/shoporder.ts