Vue3+TS+axios封装补充,加入拦截器

参考Vue3+TS+axios封装
以下封装思想来自coderwhy课程

希望在给类YPRequest传入BASE_URL,TIME_OUT的同时,可以传入拦截器

// service 统一出口
import YPRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
const ypRequest = new YPRequest({
  baseURL: BASE_URL,
  timeout: TIME_OUT
  //加入拦截器
  //hooks:{}
})

// export const ypRequest2 = new YPRequest()
// baseURL:地址一
//这里创造不同的实例,用instance作为区分
export default ypRequest

但是,能直接传入hooks吗?显然是不能的,因为传入YPRequest的参数,是有要求的。
Vue3+TS+axios封装补充,加入拦截器_第1张图片
只有下列的参数能传进去
Vue3+TS+axios封装补充,加入拦截器_第2张图片
所以为了在new YPRequest创造实例的过程中,添加拦截器,必须自定义类型符合ts的检测。
1.先定义传进来的拦截器的类型
拦截器的本质就是一个个函数

import { AxiosRequestConfig, AxiosResponse } from 'axios'
export interface YPRequestInterceptors {
  requestinterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestinterceptorCatch?: (error: any) => any
  responseinterceptor?: (config: AxiosResponse) => AxiosResponse
  responseinterceptorCatch?: (error: any) => any
} //定义传入进来的拦截器



requestinterceptor:请求拦截
requestinterceptorCatch:请求失败拦截
responseinterceptor:响应拦截
responseinterceptorCatch响应失败拦截

2.定义接口,取代之前(constructor里的参数必须是AxiosRequestConfig)

export interface YPRequestConfig extends AxiosRequestConfig {
  interceptors?: YPRequestInterceptors
}

给他拓展一个interceptors
3.重新拓展类 YPRequest

class YPRequest {
  instance: AxiosInstance //instance 用于区分,当有多个请求时,是用不同的实例

  interceptors?: YPRequestInterceptors
  constructor(config: YPRequestConfig) {
    //可以点击config进去看里面的类型
    this.instance = axios.create(config)
    this.interceptors = config.interceptors
    //以下两个ues对传入的拦截器进行调用
    this.instance.interceptors.request.use(
      this.interceptors?.requestinterceptor,
      this.interceptors?.requestinterceptorCatch
    ) //
    this.instance.interceptors.response.use(
      this.interceptors?.responseinterceptor,
      this.interceptors?.responseinterceptorCatch
    )
  }
  request(config: AxiosRequestConfig): void {
    this.instance.request(config).then((res) => {
      console.log(res.data)
    })
  }
}

4.在创建实例时传入拦截器

// service 统一出口
import YPRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
const ypRequest = new YPRequest({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
  interceptors: {
    //拦截器的本质是传入一个个函数
    requestinterceptor: (config) => {
      console.log('请求成功的拦截')
      return config
    },
    requestinterceptorCatch: (err) => {
      console.log('请求失败的拦截')
      return err
    },
    responseinterceptor: (res) => {
      console.log('响应成功的拦截')
      return res
    },
    responseinterceptorCatch: (err) => {
      console.log('响应失败的拦截')
      return err
    }
  }
})

// export const ypRequest2 = new YPRequest()
// baseURL:地址一
//这里创造不同的实例,用instance作为区分
export default ypRequest

思路总结:
1.先定义一个class YPRequest类
2.通过new YPRequest可以创造实例ypRequest,同时可以传入BASE_URL,TIME_OUT、拦截器等信息。
3.通过上一步,信息只为上面实例所有。
4.由于写好了request,所以只要调用ypRequest.request(//传入信息)即可

Vue3+TS+axios封装补充,加入拦截器_第3张图片
因为一般一个项目只请求一个BASE_URL,所以通常只创建一个实例。

补充,加上全局的拦截器(所有实例都有的拦截器)和 给某一请求添加特定拦截器

// 关于axios的封装,都封装到这个类里面,因为类具备很强的封装性,比函数要强
import axios from 'axios'
import type { AxiosInstance } from 'axios' //axios内部已经提供了关于axios实例的类型
import type { YPRequestInterceptors, YPRequestConfig } from './type'
// interface YPRequestInterceptors {
//   requestinterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
//   requestinterceptorCatch?: (error: any) => any
//   responseinterceptor?: (config: AxiosResponse) => AxiosResponse
//   responseinterceptorCatch?: (error: any) => any
// } //定义传入进来的拦截器

// interface YPRequestConfig extends AxiosRequestConfig {
//   interceptors?: YPRequestInterceptors
// }

class YPRequest {
  instance: AxiosInstance //instance 用于区分,当有多个请求时,是用不同的实例

  interceptors?: YPRequestInterceptors
  constructor(config: YPRequestConfig) {
    //可以点击config进去看里面的类型
    this.instance = axios.create(config)
    this.interceptors = config.interceptors

    //从config中取出的拦截器是对应的实例的拦截器
    this.instance.interceptors.request.use(
      this.interceptors?.requestinterceptor,
      this.interceptors?.requestinterceptorCatch
    ) //
    this.instance.interceptors.response.use(
      this.interceptors?.responseinterceptor,
      this.interceptors?.responseinterceptorCatch
    )

    //添加所有的实例都有的拦截器
    this.instance.interceptors.request.use(
      (config) => {
        console.log('这是所有实例都有的拦截器')
        return config
      },
      (err) => {
        return err
      }
    )
  }
  request(config: YPRequestConfig): void {
    if (config.interceptors?.requestinterceptor) {
      config = config.interceptors.requestinterceptor(config)
    }
    this.instance.request(config).then((res) => {
      if (config.interceptors?.responseinterceptor) {
        res = config.interceptors.responseinterceptor(res)
      }
      console.log(res.data)
    })
  }
}

export default YPRequest

//给特定实例拦截器
ypRequest.request({
  url: '/home/multidata',
  method: 'GET',
  interceptors: {
    requestinterceptor: (config) => {
      console.log('单独成功的拦截')
      return config
    }
  }
})

你可能感兴趣的:(vue.js,javascript,前端)