比如我们在这里发送了请求是没有做任何的一个拦截,之前在前面文章中有写到,如果有多个模块都用到这个请求了,这个请求里面有写共有的逻辑,比如携带token, 显示loading动画。把这些代码可以写到拦截器里面。

怎么做?

我们可以 封装 一些对应的类型

在文件A中封装一些对应的类型接口

1.先从axios 中倒入对应的类型注解

 2.定义一个对应的类型接口

3.这个类型接口里面可以定义一些hook,可以让别人通过这个类型接口给我传入哪些hook

4.要么是我们的 requset 请求拦截器,要么是我们的响应拦截器 response

5.并且在定义一个接口 来继承 我们的这个AxiosRequestConfig 接口

6. 并且对原来的类型做一个扩展

7.封装之后在对应导出

import type { AxiosResponse, AxiosRequestConfig } from 'axios'
//f封装一些对应的类型接口
export interface JYRequestInterceptors {
  //1.在这里里面可以定义一些hook,可以让别人通过这个定义的接口给我传入哪些hook
  //2.要么是我们的request 拦截器
  //拦截
  requestinterceptor: (config: AxiosRequestConfig) => AxiosRequestConfig
  //错误的拦截
  requestinterceptorCatch: (error: any) => any
  //响应成功的拦截
  responseinterceptor: (res: AxiosResponse) => AxiosResponse
  //响应失败错误的拦截
  responseinterceptorCatch: (error: any) => any
}

//4.在定义一个JYRequestConfig 接口 继承 AxiosRequestConfig
export interface JYRequestConfig extends AxiosRequestConfig {
  //对原来的类型做一个扩展
  interceptors: JYRequestInterceptors
}

在B文件里面做一个引入(在别人创建实例,添加拦截器的一个封装)

import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig } from 'axios' //instance 和 config 类型注解的倒入
import type { JYRequestInterceptors, JYRequestConfig } from './type'
// axios-->axios instance(实例)
class JYRquest {
  instance: AxiosInstance //每次创建出来都用这个实例做一个保存
  interceptors?: JYRequestInterceptors
  //创建一个类的构造器,这个构造器里面传入类的最基本的配置
  constructor(config: JYRequestConfig) {
    //axios里面有个create函数,它可以创建出来我们的实例
    this.instance = axios.create(config)
    this.interceptors = config.interceptors
    //3.拦截器
    this.instance.interceptors.request.use(
      this.interceptors?.requestinterceptor,
      this.interceptors?.requestinterceptorCatch
    )
    //4.响应拦截器
    this.instance.interceptors.response.use(
      this.interceptors?.responseinterceptor,
      this.interceptors?.responseinterceptorCatch
    )
  }
  //封装一个request 函数
  request(config: AxiosRequestConfig): void {
    this.instance.request(config).then((res) => {
      console.log(res)
    })
  }
}
export default JYRquest

在出口文件将封装对应的方法进行引入

// service 统一的出口
import JYRquest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
//axios 实例1
const JyRquest = new JYRquest({
  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 default JyRquest

关系逻辑梳理:

1.首先创建了一个 class JYRequest 的类

2.这个类在request.ts 文件里面,这个类是允许别人创建多个实例,要不要创建多个实例,根据项目的需求。例如:多个baseURlL 不一样的情况下,就可以去创建多个实例,然后每个实例都可以有自己的baseURL,可以有有自己的config。

3. 但是大多数项目,都是向一个服务器发送请求,在index.ts 导出的文件里面,是只 new 一     个JYRquest ,这个是一个实例,也叫做一个对象。以后在这个项目里面,只需要用这个对像调用request() 就可以了。或者post、get 这些方法。调的时候,永远都是用的都是这一个实例。

4.在创建实例的时候的,针对于这个实例对象可以有自己的拦截器,通俗点讲,就是要给当前这个实例对象添加拦截器,把这个拦截器放到config里面,到时候可以从config 里面取到拦截器。

5.现在添加的拦截器,是所有实例都会有的拦截器

 6.在封装的request 函数中,就不能传让别人传默认的了,因为默认的话它不能传入任何的拦截器,所以这里可以传入 JYRquestConfig ,因为这个是继承AxiosRequestConfig

import axios from 'axios'
import type { AxiosInstance } from 'axios' //instance 和 config 类型注解的倒入
import type { JYRequestInterceptors, JYRequestConfig } from './type'
// axios-->axios instance(实例)
class JYRquest {
  instance: AxiosInstance //每次创建出来都用这个实例做一个保存
  interceptors?: JYRequestInterceptors
  //创建一个类的构造器,这个构造器里面传入类的最基本的配置
  constructor(config: JYRequestConfig) {
    //axios里面有个create函数,它可以创建出来我们的实例
    this.instance = axios.create(config)
    this.interceptors = config.interceptors
    //3.从config 中取出的拦截器是对应的实例的拦截器
    this.instance.interceptors.request.use(
      this.interceptors?.requestinterceptor,
      this.interceptors?.requestinterceptorCatch
    )
    //4.响应拦截器
    this.instance.interceptors.response.use(
      this.interceptors?.responseinterceptor,
      this.interceptors?.responseinterceptorCatch
    )
    //我们可以继续添加所有的实例都有的拦截器
    this.instance.interceptors.request.use(
      (config) => {
        console.log('在我们所有的实例都有的拦截器')
        return config
      },
      (err) => {
        return err
      }
    )
    this.instance.interceptors.response.use(
      (res) => {
        return res
      },
      (err) => {
        return err
      }
    )
  }
  //封装一个request 函数
  //注意:这里让别人传config 的时候,不能传默认的了, 因为默认的话它不能传入任何的拦截器,所以这里可以传
  //这个JYRequestConfig 是继承制 AxiosRequestConfig 的
  request(config: JYRequestConfig): void {
    //判断里面是否有requestinterceptor 这个函数
    if (config.interceptors?.requestinterceptor) {
      //如果有这个函数,就将 config =config.interceptors.requestinterceptor(然后将config传进来)
      //如果这里真的有这个函数,就执行这个函数
      /**
       requestinterceptor 这个函数的目的就是对(config),
       做一个转化,转化完之后,还会把默认的config 返回回来,然后再用一个config做一个接收
       */
      config = config.interceptors?.requestinterceptor(config) //
    }
    this.instance.request(config).then((res) => {
      if (config.interceptors?.responseinterceptor) {
        res = config.interceptors.responseinterceptor(res)
      }
    })
  }
}
export default JYRquest

7.type.ts 文件中 拦截器的设置

import type { AxiosResponse, AxiosRequestConfig } from 'axios'
//f封装一些对应的类型接口
export interface JYRequestInterceptors {
  //1.在这里里面可以定义一些hook,可以让别人通过这个定义的接口给我传入哪些hook
  //2.要么是我们的request 拦截器
  //拦截
  requestinterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
  //错误的拦截
  requestinterceptorCatch?: (error: any) => any
  //响应成功的拦截
  responseinterceptor?: (res: AxiosResponse) => AxiosResponse
  //响应失败错误的拦截
  responseinterceptorCatch?: (error: any) => any
}

//4.在定义一个JYRequestConfig 接口 继承 AxiosRequestConfig
export interface JYRequestConfig extends AxiosRequestConfig {
  //对原来的类型做一个扩展
  interceptors?: JYRequestInterceptors
}

 8.在main.ts 里面,对请求拦截做一个使用(注意:可以使用拦截,也可以不用)

     

需求1:对于 每个请求都会携带对应的token

1.在发送请求的时候携带token,(携带token 应该是我们的请求拦截)

2.给 header 添加token 就可以了

3.如果属于实例的拦截的话

4.如果是属于全局所有的实例都携带的是这一个token ,应当在这里做

5.假如我们现在是单个实例.

   真实的token 应当都是我们在vuex 中获取的,或者是从服务器中又或者是登录之后从缓存中获取的。但是我们这里举例子,我们这里已经拿到了token,

import JYRquest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
//axios 实例1
const JyRquest = new JYRquest({
  baseURL: BASE_URL,
  timeout: TIME_OUT,
  interceptors: {
    requestinterceptor: (config) => {
      //真实的token  const token=vuex -->login(localStorage)
      //如果token 在有值的情况下,把它放到请求头  Authorization 授权的意思
      const token=''
      if(token){
        config.headers.Authorization=`Bearer ${token}` //Bearer 信差的意思,真实开发中,这个都会与token 结合使用
      }
      console.log('请求成功的拦截')
      return config
    },
    requestinterceptorCatch: (err) => {
      console.log('请求失败的拦截')
      return err
    },
    responseinterceptor: (res) => {
      console.log('响应成功的拦截')
      return res
    },
    responseinterceptorCatch: (err) => {
      console.log('响应失败的拦截')
      return err
    }
  }
})
export default JyRquest

需求2: 如何在服务器返回数据时候,只返回我们想要的数据

每次服务器在给我们返回的数据时,除了给了我们返回了我们想要的数据外,还给我们返回了其他的数据 ,这时候我们可以全局的实例拦截中(data的处理)

需求3: 在拦截器中做状态处理(err的处理)

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐