基于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)
  })
  

结尾

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

相关推荐
F-2H39 分钟前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
gqkmiss1 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件
m0_748247553 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255024 小时前
前端常用算法集合
前端·算法
真的很上进4 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203984 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2345 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1235 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~6 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语6 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js