当前位置:   article > 正文

typeScript 之 Axios封装(一)_对于axios封装比较好的库 ts

对于axios封装比较好的库 ts
index.ts
/* 
  `AxiosResponse`:是Axios库中定义的响应对象的类型,
                   用于表示服务器返回的响应数据,
                   包含属性:data、status、statusText、headers、config、request。
*/
import axios, { AxiosResponse } from 'axios'

/* 
  `InternalAxiosRequestConfig`:这是一个接口,它继承了`AxiosRequestConfig`接口,并且额外定义了一个`headers`属性
                                用于规范 axios 的请求配置,
*/
/*
  `AxiosInstance`:Axios实例的类型
*/
import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios'

import type {
  RequestInterceptors,
  CreateRequestConfig,
  RequestConfig,
} from './types'

class Request {
  // axios实例
  instance: AxiosInstance
  // 拦截器对象
  interceptorsObj?: RequestInterceptors<AxiosResponse>
  // 存放取消请求控制器Map
  abortControllerMap: Map<string, AbortController>

  constructor(config: CreateRequestConfig) {
    this.instance = axios.create(config)
    this.interceptorsObj = config.interceptors
    // 初始化存放取消请求控制器Map
    this.abortControllerMap = new Map()

    // 拦截器执行顺序 接口请求 -> 实例请求 -> 全局请求 -> 实例响应 -> 全局响应 -> 接口响应
    
    /*
      为什么,这里有两个`this.instance.interceptors.request.use`和两个`this.instance.interceptors.response.use`方法调用,
      因为,Axios提供了一种机制来添加拦截器,在发送请求、接收响应的过程中,执行一些额外的逻辑。

      每个`interceptors.request.use`方法调用,都用于添加一个`请求拦截器`,它会在发送请求之前执行一些逻辑,
      每个`interceptors.response.use`方法调用,都用于添加个`响应拦截器`,它会在接收到响应之后执行一些逻辑。

      第一个`this.instance.interceptors.request.use`方法调用,用于添加一个请求拦截器,
        它的逻辑是:创建一个`AbortController`实例,给请求配置对象中添加`signal`属性,并将`该请求的URL`和对应的`AbortController`实例存储到`abortControllerMap`中。

      第二个`this.instance.interceptors.request.use`方法调用,是使用实例拦截器,
        它的逻辑是:将在`config.interceptors`对象中定义的请求拦截器函数,作为参数传递给 `request.use` 方法。

      第一个`this.instance.interceptors.response.use`方法调用,用于添加一个响应拦截器,
      它的逻辑是:在接收到响应后从`res`对象中,取出响应的数据,并从`abortControllerMap`中删除对应的URL。

      第二个`this.instance.interceptors.response.use`方法调用,是使用实例拦截器,
      它的逻辑是:将在`config.interceptors`对象中定义的响应拦截器函数,作为参数传递给 `response.use` 方法。

      通过添加拦截器,可以在请求和响应的不同阶段执行一些通用的逻辑,例如添加请求头、处理错误、修改请求或响应数据等。
    */
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        const controller = new AbortController()
        const url = config.url || ''
        config.signal = controller.signal
        this.abortControllerMap.set(url, controller)
        return config
      },
      (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,
    )

    // 全局响应拦截器保证最后执行
    // Axios的响应对象,包括config对象、data对象、headers对象、request对象、status状态码、statusText字符串
    this.instance.interceptors.response.use(
      // 因为,我们接口的数据都在res.data下,所以我们直接返回res.data
      (res: AxiosResponse) => {
        const url = res.config.url || ''
        this.abortControllerMap.delete(url)
        return res.data
      },
      (err: any) => err,
    )
  }

  request<T>(config: RequestConfig<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      // 如果我们为单个请求设置拦截器,这里使用单个请求的拦截器
      if (config.interceptors?.requestInterceptors) {
        config = config.interceptors.requestInterceptors(config as any)
      }
      /*
        this.instance.request(config) 是使用 Axios 实例发送 HTTP 请求的方法,
        this.instance是一个Axios实例,通过调用 request(config) 方法可以发送HTTP请求,
        config 参数是一个`AxiosRequestConfig`对象,用于配置请求的相关参数,例如请求的 URL、请求方法、请求头、请求体等。

        Axios提供了多种方法用于发送不同类型的请求,例如 get()、post()、put() 等,但它们都是通过调用 request(config) 方法实现的,
        request(config) 方法可以接收一个 AxiosRequestConfig 对象作为参数,该对象包含了发送请求所需的所有配置信息,然后返回一个 Promise 对象,用于处理请求的响应。

        所以,this.instance.request(config) 表示使用 Axios 实例发送一个 HTTP 请求,并传入配置参数 config。
      */
      this.instance
        .request<any, T>(config)
        .then(res => {
          // 如果我们为单个响应设置拦截器,这里使用单个响应的拦截器
          if (config.interceptors?.responseInterceptors) {
            res = config.interceptors.responseInterceptors(res)
          }
          resolve(res)
        })
        .catch((err: any) => {
          reject(err)
        })
        .finally(() => {})
    })
  }

  /*
    取消全部请求
    for (const [, controller]   of   controllerMap) 表示只获取 Map 中的值,而不获取键
  */
  cancelAllRequest() {
    for (const [, controller] of this.abortControllerMap) {
      controller.abort()
    }
    this.abortControllerMap.clear()
  }

  /**
   * 取消指定的请求
   * @param url 待取消的请求URL
   */
  cancelRequest(url: string | string[]) {
    const urlList = Array.isArray(url) ? url : [url]
    for (const _url of urlList) {
      this.abortControllerMap.get(_url)?.abort()
      this.abortControllerMap.delete(_url)
    }
  }
}

export default Request

export { RequestConfig, RequestInterceptors }


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/299743
推荐阅读
相关标签
  

闽ICP备14008679号