Vue在请求拦截器中进行,全局接口防抖拦截

  • 其实实现上一个请求结束前禁止下次请求的方法很多,最常见的其实就是防抖等等,但如果对所有接口都进行这个操作就很繁琐,就算写一个公共的方法也是即此。
  • 既然上面的方法繁琐,那不如从根源解决问题,已知所有的接口都会通过请求拦截器/请求响应器,那么可以从此处做手脚,一次性解决所有问题。

1.最基础的请求基础代码

import axios from 'axios'
import { getItem, removeItem } from '@/utils/token'
import { Message } from 'element-ui'
import router from '@/router'
const request = axios.create({
  baseURL: "/api",
})
// 请求拦截器
request.interceptors.request.use(function (config) {
  config.headers.Authorization = `Bearer ${getItem("token")}`
  return config;
})
// 响应拦截器
request.interceptors.response.use(function (config) {
  const { status, message } = config.data
  if (status == '500') {
    Message.error('登录已过期,请重新登录')
    removeItem('token')
    router.push('/login')
  } else if (status !== '200' && status !== '500') {
    Message.error(message)
  }
  return config
}, error => {
  console.log(error);
  return Message.error(error)
})
export default request

2. 获取这次请求的请求信息,并做重复拦截

let requestList = []
// 请求拦截器
// 同时记录请求地址与请求方式防止拦截错误 
request.interceptors.request.use(function (config) {
    // headers:{
    //   // 不进行拦截
    //   serviceFiler:true
    // }
    // 记录当前接口信息进行拦截
    if (!config.headers.serviceFiler) {
      if (!requestList.some(x => x.config === `${config.url}&${config.method}`)) {
        requestList.push({ config: `${config.url}&${config.method}` })
      } else {
        return false
      }
    }

  config.headers.Authorization = `Bearer ${getItem("token")}`
  return config;
})

3. 请求结束后清除此接口信息

// 响应拦截器
request.interceptors.response.use(function (config) {
    // 移除已响应完成的接口信息 - 延迟 300 毫秒, 防止接口响应速度过快,页面还未及时更新的情况
    setTimeout(() => {
      requestList = requestList.filter((x, index) => x.config !== `${res.config.url}&${res.config.method}`)
    }, 300);

  const { status, message } = config.data
  if (status == '500') {
    Message.error('登录已过期,请重新登录')
    removeItem('token')
    router.push('/login')
  } else if (status !== '200' && status !== '500') {
    Message.error(message)
  }
  return config
}, error => {
  // 如果接口是被拦截,抛出错误
  if (error == `TypeError: Cannot create property 'headers' on boolean 'false'`) return Promise.reject('接口重复调用!')
  return Message.error(error)
})
  • 如果接口被拦截会使用Promise.reject()直接抛错,此时不会影响代码正常运行。
    效果图

4. 完整代码

import axios from 'axios'
import { getItem, removeItem } from '@/utils/token'
import { Message } from 'element-ui'
import router from '@/router'
const request = axios.create({
  baseURL: "/api",
})
let requestList = []
// 请求拦截器
// 同时记录请求地址与请求方式防止拦截错误 
request.interceptors.request.use(function (config) {
    // headers:{
    //   // 不进行拦截
    //   serviceFiler:true
    // }
    // 记录当前接口信息进行拦截
    if (!config.headers.serviceFiler) {
      if (!requestList.some(x => x.config === `${config.url}&${config.method}`)) {
        requestList.push({ config: `${config.url}&${config.method}` })
      } else {
        return false
      }
    }
  config.headers.Authorization = `Bearer ${getItem("token")}`
  return config;
})
// 响应拦截器
request.interceptors.response.use(function (config) {
  // 移除已响应完成的接口信息 - 延迟 500 毫秒, 防止接口响应速度过快,页面还未及时更新的情况
    setTimeout(() => {
      requestList = requestList.filter((x, index) => x.config !== `${res.config.url}&${res.config.method}`)
    }, 500);
  const { status, data, message } = config.data
  if (status == '500') {
    Message.error('登录已过期,请重新登录')
    removeItem('token')
    router.push('/login')
  } else if (status !== '200' && status !== '500') {
    Message.error(message)
  }
  return data
}, error => {
  // 如果接口是被拦截,抛出错误
  if (error == `TypeError: Cannot create property 'headers' on boolean 'false'`) return Promise.reject('接口重复调用!')
  return Promise.reject(error);
})
export default request

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容