在项目中用ts封装axios

本文介绍如何在项目中使用TypeScript封装axios,包括基础封装和拦截器封装。基础封装通过创建一个类来增强封装性。拦截器封装分为类拦截器、实例拦截器和接口拦截器。类拦截器在类中设置axios实例的拦截器,实例拦截器允许在每个实例中设置不同的拦截行为,接口拦截器则允许对特定接口进行拦截操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在项目中用ts封装axios

基础封装

import axios from 'axios'
import type {AxiosInstance,AxiosRequestConfig,AxiosResponse} from 'axios'

class Request{
    //axios实例,并将它作为 类的instance属性(属性名自定义)
    instance:AxiosInstance
    constructor(config:AxiosRequestConfig){
        this.instance = axios.create(config)
    }
	request(config:AxiosRequestConfig){
        return this.instanse.request(config) //类的方法request是绑定在原型上的,所以实例也可以访问到
    }
}

这里讲题封装为一个类,而不是一个函数,是因为类可以创建多个实例,适用范围更广,封装性更强。

拦截器封装

先封装一下拦截器,这个拦截器分三种:

  • 类拦截器
  • 实例拦截器
  • 接口拦截器
1. 类拦截器

类拦截器比较容易实现,只要在类中对axios.create()创建的实例,调用interceptors 下的两个拦截器即可,实例代码如下:

constructor(config:AxiosRequestConfig){
        this.instance = axios.create(config)
    	
    	this.instance.interceptors.request.use(
        	(res:AxiosRequestConfig )=>{
                console.log('全局请求拦截器') 
    			return res
            },
            (err:any)=>err,
        )
        this.instance.interceptors.response.use(
        	(res.AxiosResponse)=>{
                console.log('全局响应拦截器')
                return res.data,//这里对响应拦截器做了一个简单的处理,就是将请求进行返回,因为我们的接口请求中的数据主要存放在.data中,跟.data同级的属性基本不需要
            }
        )
    }
2. 实例拦截器

实例拦截器是为了保证封装的灵活性,因为每一个实例中拦截后的操作可能不一样,所以定义实例时,允许我们传入拦截器。

首先我们定义一下 interface,方便类型提示:

//types.ts
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
export interface RequestInterceptors {
  // 请求拦截
  requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestInterceptorsCatch?: (err: any) => any
  // 响应拦截
  responseInterceptors?: (config: AxiosResponse) => AxiosResponse
  responseInterceptorsCatch?: (err: any) => any
}
// 自定义传入的参数
export interface RequestConfig extends AxiosRequestConfig {
  interceptors?: RequestInterceptors
}

定义好基础的拦截器后,我们需要改造我们传入的参数的类型,因为axios提供的AxiosRequestConfig是不允许我们传入拦截器的,所以说我们自定义了RequestConfig,让其继承与AxiosRequestConfig
剩余部分的代码:

//index.ts
import axios Axios,{AxiosResponse} from 'axios'
import type {AxiosInstance,AxiosRequestConfig} from 'axios'
import type{RequestConfig,RequestInterceptors} from './types.ts'
class Request{
    //axios实例
    instance:AxiosInstance
    //拦截器对象
    interceptorsObj?:RequestInterceptors
    constructor(config:RequestConfig){
        this.instance = axios.create(config)
        this.interceptorsObj = config.interceptors
        this.instance.interceptors.request.use(
        	(res: AxiosRequestConfig)=>{
                console.log('全局请求拦截器')
        		return res
            },
            (err: any)=>{
                console.log(err)
            }
        )
         // 使用实例拦截器
    this.instance.interceptors.request.use(
      this.interceptorsObj?.requestInterceptors,
      this.interceptorsObj?.requestInterceptorsCatch,
    )
    this.instance.interceptors.response.use(
      this.interceptorsObj?.responseInterceptors,
      this.interceptorsObj?.responseInterceptorsCatch,
    )
    // 全局响应拦截器保证最后执行
    this.instance.interceptors.response.use(
      // 因为我们接口的数据都在res.data下,所以我们直接返回res.data
      (res: AxiosResponse) => {
        console.log('全局响应拦截器')
        return res.data
      },
      (err: any) => err,
    )

拦截器的执行顺序为:实例请求–>类请求–>实例响应–>类响应,这样我们就可以在实例拦截器上做出不同的拦截。

3. 接口拦截

现在我们对单一接口进行拦截操作,首先我们将AxiosRequestConfig类型修改为RequestConfig允许传递拦截器;然后我们在类拦截器中将接口请求的数据进行了返回,也就是说在require()方法中得到的类型就不是AxiosResponse类型了。

我们查看axios的index.d.ts中,对require()方法的类型定义如下:

// type.ts
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
复制代码

也就是说它允许我们传递类型,从而改变require()方法的返回值类型,我们的代码如下:

// index.ts
request<T>(config: RequestConfig): Promise<T> {
  return new Promise((resolve, reject) => {
    // 如果我们为单个请求设置拦截器,这里使用单个请求的拦截器
    if (config.interceptors?.requestInterceptors) {
      config = config.interceptors.requestInterceptors(config)
    }
    this.instance
      .request<any, T>(config)
      .then(res => {
        // 如果我们为单个响应设置拦截器,这里使用单个响应的拦截器
        if (config.interceptors?.responseInterceptors) {
          res = config.interceptors.responseInterceptors<T>(res)
        }

        resolve(res)
      })
      .catch((err: any) => {
        reject(err)
      })
  })
}

这里还存在一个细节,就是我们在拦截器接受的类型一直是AxiosResponse类型,而在类拦截器中已经将返回的类型改变,所以说我们需要为拦截器传递一个泛型,从而使用这种变化,修改types.ts中的代码,示例如下:

// index.ts
export interface RequestInterceptors {
  // 请求拦截
  requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestInterceptorsCatch?: (err: any) => any
  // 响应拦截
  responseInterceptors?: <T = AxiosResponse>(config: T) => T
  responseInterceptorsCatch?: (err: any) => any
}

请求接口拦截是最前执行,而响应拦截是最后执行。
未完。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值