封装axios二方包

前言

在前端项目开发中,直接使用 axios 发起网络请求虽然简单高效,但在大型项目或多项目协作中存在维护性差、重复代码多等问题。因此,二次封装axios的二方包是有必要的

功能需求

1. 统一请求配置

通过封装可以设置全局默认配置(如超时时间、基础路径、请求头等),避免每个项目都手动重复设置。

2. 拦截器统一管理

封装后可以集中管理请求和响应拦截器,实现通用逻辑(如错误统一处理等)

3. 接口返回格式标准化

封装可统一处理响应数据结构,确保所有接口返回的数据格式一致,便于业务层消费

4. 支持多个项目的复用

将封装后的工具打包插件,可在多个项目中复用,减少重复开发工作。

5. 增强可维护性和扩展性

当需要升级功能或者变更统一逻辑时,只需修改封装层,无需改动业务代码,降低耦合度。

6. 统一错误处理机制

可在封装中统一处理网络异常、业务错误码(如 401、500),并提供友好提示或自动重试机制。

7. 提升开发体验

封装后对外暴露简洁的 API,如 get, post 方法,让开发者更专注于业务逻辑而非底层请求细节。

功能设计

1.类接口设计

封装一个接口类,包含一个构造函数constructor(options: RequestClientOptions = {})

初始化Axios实例时可以传入一些配置参数,比如timeout超时时间、baseUrl,或是拦截器等

2.主要成员变量
instance AxiosInstance Axios实例
addRequestInterceptor Function 自定义添加的请求拦截
addResponseInterceptor Function 自定义添加的相应拦截
requestConfig 记录config配置
download Function 通过一个单独的类生成文件下载方法
upload Function 通过一个单独的类生成文件上传方法
loading boolean 记录是否需要展示loading加载状态
3.默认的全局配置

在constructor中有个defaultConfig以便不用过多配置,如下

js 复制代码
class RequestClient {
    constructor(options: RequestClientOptions = {}) {
        const defaultConfig: RequestClientOptions = {
          headers: {
            'Content-Type': 'application/json;charset=utf-8',
          },
          responseReturn: 'raw',
          // 默认超时时间
          timeout: 10000,
        };
    }
}
4.请求参数处理

初始化对axios的配置参数paramsSerializer做处理,支持自定义参数序列化方式,也可以使用默认值

5.默认的全局拦截

在内部会定义默认的全局请求拦截和响应拦截,譬如处理请求时的页面加载loading,处理通用场景下异常status:403,500等状态码异常错误提示等(支持配置)

6.通用请求工具函数

封装通用请求工具函数request,并支持自定义或默认响应泛型供用户消费,并根据request进一步封装get,post,delete,put/patch供使用

js 复制代码
type ResponseType<T = any> = {
    data: T
    code: number
    message: string
}
type RequestMethods = Extract<
  Method,
  'get' | 'post' | 'put' | 'delete' | 'patch' | 'option' | 'head'
>

public async request<T = ResponseType>(
    method: RequestMethods
    url: string,
    config: RequestClientConfig,
): Promise<AxiosResponse<T>> {
...
}
7.取消请求

部分场景下存在接口需主动取消请求,如tab切换过程中存在接口未响应的,在切换后不需要请求时取消请求,避免存在接口排队的情况

类设计图

classDiagram class RequestClient { +_instance: AxiosInstance +_clientConfig: RequestClientOptions +_interceptorsConfig: InterceptorsConfig +addRequestInterceptor: Function +addResponseInterceptor: Function +upload: Function +download: Function +downloadByPost: Function +downloadByBlob: Function +downloadByBlobPost: Function +requestControllers: Map +request(method, url, config?: RequestClientConfig): Promise +get(url, config?: RequestClientConfig): Promise +post(url, data?, config?: RequestClientConfig): Promise +put(url, data?, config?: RequestClientConfig): Promise +patch(url, data?, config?: RequestClientConfig): Promise +delete(url, param?, config?: RequestClientConfig): Promise +initSuccessCodes(successCodes: number | number[] | undefined | null): Array +initRequestInterceptor(): void +initResponseInterceptor(): void +addRequestController(key): void +removeRequestController(key): void +cancelRequest(key, message?): void +cancelAllRequests(message?): void } class FileDownloader { +client: RequestClient +notification: NotificationConfig +message: MessageConfig +download(url, config): Promise +downloadByPost(url, data, config): Promise +downloadByBlob(url, config): Promise +downloadByBlobPost(url, data, config): Promise } class FileUploader { +client: RequestClient +upload(url, data, config)?: Promise } class Interceptormanager { +instance: AxiosInstance +addRequestInterceptor() RequestInterceptorConfig +addResponseInterceptor() ResponseInterceptorConfig } RequestClient --> FileDownloader : 依赖 RequestClient --> FileUploader : 依赖 RequestClient --> Interceptormanager : 依赖
使用设计
  1. 实例初始化
js 复制代码
// 使用默认
const  http = new RequestClient()
// 添加配置项
const  http = new RequestClient(
    config: RequestClientOptions
)

2.自定义config配置

首先config的类型是RequestClientOptions,他继承自AxiosRequestConfig,并在其基础上增加了一些其他的配置属性,譬如paramsSerializer指定序列化,interceptors初始化时指定业务的自定义拦截器等

或是初始化完成之后通过调用实例中的addRequestIntercepter或addResponseIntercepter去给axios实例的interceptors添加拦截器处理

  1. 业务代码使用
csharp 复制代码
// api接口,如module=user
const http = new RequestClient()
// 1. 直接使用request方法
const _userInfo = (params) => {
    return  http.request<ResponseType>('get', url, {params})
}
// 2.使用具体的方法
const _userInfo = (params) => {
    return  http.get<ResponseType>( url, {params})
}

这里的DataType是接口返回的data中数据类型,方便提示

调用流程图
相关推荐
天天扭码几秒前
很全面的前端面试——CSS篇(上)
前端·css·面试
EndingCoder3 分钟前
搜索算法在前端的实践
前端·算法·性能优化·状态模式·搜索算法
sunbyte8 分钟前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleVerticalSlider(双垂直滑块)
前端·javascript·css·vue.js·vue
Favor_Yang12 分钟前
SQL Server通过存储过程实现HTML页面生成
前端·信息可视化·sqlserver·存储过程
中微子1 小时前
JavaScript事件循环机制:面试官最爱问的10个问题详解
前端
Eighteen Z1 小时前
CSS揭秘:10.平行四边形
前端·css·css3
拾光拾趣录1 小时前
虚拟DOM
前端·vue.js·dom
爱学习的茄子1 小时前
JavaScript事件循环深度解析:理解异步执行的本质
前端·javascript·面试
1024小神1 小时前
cocos游戏开发中多角色碰撞,物理反弹后改变方向的实现逻辑
前端·javascript
摆烂为不摆烂1 小时前
😁深入JS(五): 一文让你完全理解 hash 与 history 路由,手写前端路由
前端