基于Vue3+TS对Axios进行相对全面的封装

Axios + TS 弱鸡封装

实现功能

1.可以创建多个创建多个互不干扰,完全独立的axios实例

2.通过创建的实例调用各种方法(request,get,post......)

封装的前置认识

类的基本使用

TS

AxiosInstance ------ axios实例的类型

AxiosResponse ------ 响应的数据类型

InternalAxiosRequestConfig ------ 传入配置config的类型/请求的数据类型

为什么要对Axios进行封装

弊端:对axios的依赖太强了,如果日后更换网络请求库会很麻烦

好处:将各个请求相同的配置写在一块,减少重复的垃圾代码

封装过程

一.创建多个axios实例

可能应用场景:你有多个baseurl,需要去多个服务器请求数据,这时候就需要创建多个互不干扰,完全独立的axios实例

我们通过以下代码实现

javascript 复制代码
// service/index
import TTRequest from './request'
const ttRequest = new TTRequest({
    baseURL:'http://201314xxx'
    timeout:1000
})
const ttRequest2 = new TTRequest({
    baseURL:'http://666666xxx'
    timeout:2000
})
export default ttRequest
typescript 复制代码
// service/request/index.ts
import axios from 'axios'
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios'
​
class TTRequest {
  instance: AxiosInstance //该类型是axios里面规定好的,不是我瞎编的
​
  constructor(config: InternalAxiosRequestConfig) {
    this.instance = axios.create(config)
  }
}
​
export default TTRequest

拦截器的封装

一.全局拦截器的封装

在constructor直接设置拦截器,因为在new TTRequest()时,会执行constructor的代码,这样所有实例都具有此拦截器

javascript 复制代码
class TTRequest {
  instance: AxiosInstance
  constructor(config: AxiosRequestConfig) {
  // 创建axios实例
    this.instance = axios.create(config)
    
  // 保存拦截器
    this.interceptors = config.interceptors
    
  //全局拦截器(所有实例都有的拦截器)
    this.instance.interceptors.request.use(
      (config) => {
        console.log('全局request成功')
        return config
      },
      (err) => {
        console.log('全局request失败')
        return err
      }
    )
​
    this.instance.interceptors.response.use(
      (config) => {
        console.log('全局response成功')
        return config
      },
      (err) => {
        console.log('全局response失败')
        return err
      }  
  }
二.单个实例拦截器的封装(仅在一个实例有效的)

想要实现只在单个实例中生效的拦截器,我希望在该类中传递我们需要的拦截器。

但是因为TTRequest 想要我们传递InternalAxiosRequestConfig类型的参数,而InternalAxiosRequestConfig却是没有拦截器interceptors属性

所以我们需要为InternalAxiosRequestConfig扩展一个interceptors属性,用到的是接口继承的知识点

步骤:

一. 用interface接口定义类型 TTRequestInterceptors

二. 在 TTRequestConfig 中扩展 interceptors 拦截器属性

三. 为 TTRequest 添加一个interceptors ,并声明其类型为TTRequestInterceptors

四. 再将每个实例的拦截器对象从config.interceptors拿出,添加到axios的实例拦截器里面

typescript 复制代码
interface TTRequestInterceptors {
  requestInterceptor?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig
  requestInterceptorCatch?: (err: any) => any
  responseInterceptor?: (config: AxiosResponse) => AxiosResponse
  responseInterceptorCatch?: (err: any) => any
}
​
// 为InternalAxiosRequestConfig类型扩展interceptors属性
interface TTRequestConfig extends InternalAxiosRequestConfig {
  interceptors?: TTRequestInterceptors
}
​
class TTRequest {
  instance: AxiosInstance
  interceptors?: TTRequestInterceptors
  constructor(config: TTRequestConfig) {
  // 创建axios实例
    this.instance = axios.create(config)
    
  // 保存拦截器
    this.interceptors = config.interceptors
    
  //全局拦截器代码省略  
    
  // 调用单个实例拦截器  
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    )
  } //注意此时的InternalAxiosRequestConfig已经被换成TTRequestConfig
  }

方法的封装

为了在调用ttRequest的时候能拿到请求成功返回的数据,我们需要返回一个Promise,这样就可以在调用时.then得到数据

补充:所有方法封装都是调用的request函数

javascript 复制代码
// 方法封装
  request<T>(config: TTRequestConfig): Promise<T> {
    return new Promise((resolve) => {
      this.instance.request(config).then((res) => resolve(res))
    })
  }
​
  get<T>(config: TTRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'GET' })
  }
  post<T>(config: TTRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'POST' })
  }
  delete<T>(config: TTRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'DELETE' })
  }
  patch<T>(config: TTRequestConfig): Promise<T> {
    return this.request<T>({ ...config, method: 'PATCH' })
  }
typescript 复制代码
interface DateType {
  data: any
  returnCode: String
  success: Boolean
}
// 调用ttRequest
ttRequest
  .get<DateType>({
    url: 'xxxxx'
  })
  .then((res) => {
    console.log(res)
  })
  

结尾

第一次写博客,如果有写的不对的,或者是不清楚的,欢迎各位大神批评指正,大家互相交流共同进步

相关推荐
FungLeo17 分钟前
Flutter Web 中文字体困境与渲染器选择:CanvasKit vs HTML renderer 实战
前端·flutter·html
敲代码的玉米C39 分钟前
我修的那个 bug,制造了另一个 bug
前端·人工智能·架构
gis开发之家1 小时前
《Vue3 从入门到大神50篇》Vue3 源码详解(二十):生命周期钩子源码解析 —— onMounted / onUpdated 如何实现?
前端·javascript·前端框架·vue3·vue3源码
Narrastory1 小时前
我用 Claude Code 写代码不到 2 小时,却花了 3 天做完这个软件—Vibe Coding 的正确姿势,是设计不是生成
前端·人工智能·github
Enaium1 小时前
我实现了KMP的SDL绑定并编写了高性能软光追
前端·kotlin
古夕1 小时前
本地正常线上白屏:一次路由切换后刷新恢复问题的排查与修复
前端·ai编程
栀鸢ouo1 小时前
解决Element Plus表格展开行横向溢出、滚动截断问题(项目实战方案)
前端·vue.js
用户39051332192881 小时前
写了5年JS,才发现这10个方法能少写一半代码
前端
平凡的阿泽1 小时前
我用TRAE Work手搓了一个「谁是卧底」小游戏
前端·javascript
一心只读圣贤书1 小时前
AI 辅助前端视觉回归治理:从截图基线到变更解释
前端·人工智能