Vue公共loading升级版(处理并发异步差时响应)

公共loading是项目系统中很常见的场景,处理方式也不外乎三个步骤:

1.通过全局状态管理定义状态值(vuex、pinia等)。

2.在程序主入口监听状态值变化,从而展示/隐藏laoding动画。

3.在请求和相应拦截器中变更状态值。

第一二步骤处理大同小异,但在第三步中,网上很多博文分享的方法是:在请求拦截中展示loading,在响应拦截器中判断收到成功响应时直接隐藏loading,这种方法看似可行但实际过程中却有问题。

例如,假设在第0秒时同时向后台发送了两个异步请求A和B,由于网络或处理逻辑不同,A请求0.5秒秒收到成功响应,B请求2秒才收到。那在第0.5秒,响应拦截器就会把loading状态变更,结束loading动画,但此时B请求还没收到返回。如果用户接下来的操作同时需要A和B请求的数据,提前结束动画会让用户体检变差。

解决思路:
定义一个全局对象来存储每个接口的响应状态,直到每个请求接口都收到响应才变更状态,结束loading动画。因为键名的唯一性,可以使用接口路径(或唯一接口编号)作为键名。请求时添加一个键值对,响应时变更键值,同时遍历对象状态值进行判断

复制代码
let apiStatusList ={
  '/api/a':true,//true请求中
  '/api/b':false //false请求完成
}

具体操作如下(以vue3的pinia为例):

定义一个loading.js

复制代码
import { defineStore } from 'pinia';
export const useLoadStore = defineStore('storeLoading', {
  state: () => {
    return {
      apiStatusList:{},
      loading:false, //网络加载状态,true加载中
    };
  },
  actions: {
    updateLoadingState(value){
      this.loading = value
    },
    setApiStatusList(value){
      this.apiList = value;
    }
  }
});

拦截器处理:

复制代码
import axios from 'axios';
import { useLoadStore } from '../stores/loading';

const request = axios.create();
//请求拦截
request.interceptors.request.use(
  (config) => {
    //公共loading
    const loadStore = useLoadStore();
    let statusList = { ...loadStore.apiStatusList };
    statusList[config.url] = true; //接口赋值为请求中
    loadStore.setApiStatusList(statusList);
    if (!loadStore.loading) {  //判断loading是否正在展示中
      loadStore.updateLoadingState(true);
    }

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
)

//响应拦截
request.interceptors.response.use(
  (response) => {
    const loadStore = useLoadStore();
    let statusList = { ...loadStore.apiStatusList };
    statusList[response.config.url] = false;  ////接口赋值为请求完成
    if (!Object.values(statusList).includes(true)) { //遍历对象,判断接口是否全部返回
      if (loadStore.loading) {
        loadStore.updateLoadingState(false);
        loadStore.setApiStatusList({});
      }
    } else {
      loadStore.setApiStatusList(statusList);
    }
  },
  (error) => {//有接口报错,重置loading
    const loadStore = useLoadStore();
    if (loadStore.loading) {
      loadStore.updateLoadingState(false);
      loadStore.setApiStatusList({});
    }
  }
)

App.vue监听状态变化

复制代码
//监听store状态值时需要传入function
watch(()=>loadStore.loading,(newValue, oldValue)=>{
  if(newValue){
    showLoadingToast({
      duration: 0,
      forbidClick: true,
    });
  }else{
    closeToast();
  }
})
相关推荐
!win !14 小时前
通过重写组件轻松掌握用JSX写Vue项目
vue·jsx
zy happy2 天前
RuoyiApp 在vuex,state存储nickname vue2
前端·javascript·小程序·uni-app·vue·ruoyi
小阳生煎2 天前
Vue实现全局设置一个刷新按钮 只刷新当面路由页面 不跳转操作功能
vue.js·vue
Zzzzzxl_2 天前
互联网大厂前端面试实录:HTML5、ES6、Vue/React、工程化与性能优化全覆盖
性能优化·vue·es6·react·html5·前端面试·前端工程化
李慕婉学姐2 天前
【开题答辩过程】以《基于微信小程序垃圾分类图像识别技术实现》为例,不会开题答辩的可以进来看看
spring boot·微信小程序·vue
故事不长丨3 天前
【Java SpringBoot+Vue 实现视频文件上传与存储】
java·javascript·spring boot·vscode·后端·vue·intellij-idea
咚咚咚小柒3 天前
【前端】Webpack相关(长期更新)
前端·javascript·webpack·前端框架·node.js·vue·scss
老华带你飞4 天前
房屋租赁|房屋出租|房屋租赁系统|基于Springboot的房屋租赁系统设计与实现(源码+数据库+文档)
java·数据库·spring boot·vue·论文·毕设·房屋租赁系统
前端摸鱼匠4 天前
Vue 3 事件修饰符全解析:从 .stop 到 .passive,彻底掌握前端交互的艺术
前端·vue.js·node.js·vue·交互
Crazy Struggle4 天前
.NET 8.0 + Vue 企业级在线培训系统(开源、免费、支持多种主流数据库)
vue·.net 8.0·后台管理系统