封装axios使用ant-design-vue的spin实现全局加载状态

业务需求

在发送请求的过程中显示加载状态,在全局进行应用,发送请求前将ant-design-vue的spin组件的状态设置为true,发送完之后将状态设置为false。

误区及难点

本打算在axios的请求拦截器和响应拦截器做处理,使用pinia状态管理进行spin状态的改变的记录。但忽略了一个页面中可能有多个请求,每次发生一个请求就开启关闭,单个请求响应时间短,多个请求没办法知道什么时候所有请求结束,页面上显示不出来加载状态。

解决方法

这里做了一个请求池,在发送请求时记录请求,响应结束将请求从请求池里面移除。然后监听请求池的状态,当请求池中的请求为0时,变更store里面spin的状态为false。

页面布局

<script setup lang="ts">
import { ref } from 'vue'
import {useCommonStore } from '@/store'
import { Spin } from 'ant-design-vue'//这里用的是按需引入
const commonStore = useCommonStore()
</script>

<template>
  <Spin :spinning="commonStore.spinning">
    <div
    class="w-screen h-screen p-t-60px bg-[#f8f9fd]"
  >
    <div class="bg-[#fff] p-[10px]">
      <RouterView />
    </div>
  </div>
  </Spin>
</template>

store文件

import { defineStore } from 'pinia'
export const useCommonStore = defineStore('common-store', {
  state: (): CommonState => ({
    spinning: false,
  }),

  actions: {
    setCurRequestNum(num: number) {
      this.spinning = num !== 0//控制spin组件的状态
    }
  },
})

axios二次封装 

import axios, { AxiosResponse } from 'axios'
import { getToken } from '../util/index.js'
import {useCommonStore } from '@/store'
import envConfig from '../../config'
const pendingMap = new Map()//请求池,存储请求

const service = axios.create({
  baseURL: envConfig.api,
})

//获取请求的信息,进行记录
const getPendingKey=(config:any)=>{
  let { url, method, params, data } = config
  if (typeof data === 'string') data = JSON.parse(data || '{}') // response里面返回的config.data是个字符串对象
  return [url, method, JSON.stringify(params), JSON.stringify(data || {})].join('&')//将url请求路径,method方法,params参数,data参数以&连接起来进行
}

//添加信息到请求池中
const addPending = (config: any) => {
  const pendingKey = getPendingKey(config)
  config.cancelToken =
    config.cancelToken ||
    new axios.CancelToken((cancel) => {//axios 取消请求(axios中取消请求情况分为1:取消该请求之后的相同请求;2:取消该请求之前的相同请求)
      if (!pendingMap.has(pendingKey)) {
        pendingMap.set(pendingKey, cancel)
          const commonStore = useCommonStore()
          commonStore.setCurRequestNum(pendingMap.size)//记录请求池中请求的数量
      }
    })
}

const removePending = (config: any) => {
  const pendingKey = getPendingKey(config)
  if (pendingMap.has(pendingKey)) {
    const cancelToken = pendingMap.get(pendingKey)
    cancelToken(pendingKey)//如果请求过则取消请求
    pendingMap.delete(pendingKey)
    setTimeout(() => {
      const commonStore = useCommonStore()
      commonStore.setCurRequestNum(pendingMap.size)
    }, 100)
  }
}

service.interceptors.request.use(
  (config) => {
     removePending(config)//移除重复的请求
     addPending(config)//将新的请求添加进去
    const token = getToken()
    if (token) {
      config.headers['X-Auth-Token'] = token
    }
    return config
  },
  (error) => {
    return Promise.reject(error.response)
  }
)

service.interceptors.response.use(
  (response: AxiosResponse): AxiosResponse => {
     removePending(response.config)
    return response
  },
  (error) => {
    return Promise.reject(error)
  }
)

export default service

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值