使用TS封装axios

一、基本封装

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

class Request {
  // axios 实例
  instance: AxiosInstance

  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create(config)
  }
  request(config: AxiosRequestConfig) {
    return this.instance.request(config)
  }
}

export default Request

二、拦截器封装

1.类拦截器:在类中对axios.create()创建的实例调用interceptors下的两个拦截器

// index.ts
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.data下,所以我们直接返回res.data
    (res: AxiosResponse) => {
      console.log('全局响应拦截器')
      return res.data
    },
    (err: any) => err,
  )
}

2.实例拦截器:保证了封装的灵活性,每一个实例中的拦截器后的处理可能不一样
拦截器的执行顺序为实例请求→类请求→实例响应→类响应;这样可以在请求的时候做一些不同的拦截

基础拦截
// 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, { AxiosResponse } from 'axios'
import type { AxiosInstance, AxiosRequestConfig } from 'axios'
import type { RequestConfig, RequestInterceptors } from './types'

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) => 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允许传递拦截器;在类拦截器中将接口请求的数据进行了返回,也就是说在request()方法中得到的类型就不是AxiosRequest类型

查看axios的index.d.ts中对**request()**方法的类型如下:

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

也就是说允许我们传递的类型,从而改变request()方法的返回值类型:

// 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)
      })
  })
}

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

ps以上内容借鉴掘金创作者一碗周

你可能感兴趣的:(TypeScript,typescript)