写点什么

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

  • 2023-11-21
    福建
  • 本文字数:1485 字

    阅读完需:约 5 分钟

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


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


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


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


第一二步骤处理大同小异,但在第三步中,网上很多博文分享的方法是:在请求拦截中展示 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状态值时需要传入functionwatch(()=>loadStore.loading,(newValue, oldValue)=>{  if(newValue){    showLoadingToast({      duration: 0,      forbidClick: true,    });  }else{    closeToast();  }})
复制代码


文章转载自:波特卡斯D

原文链接:https://www.cnblogs.com/zyj-Blogs/p/17844283.html

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Vue公共loading升级版(处理并发异步差时响应)_Vue_快乐非自愿限量之名_InfoQ写作社区