Vue缓存字典值减少网络请求次数,解决同样参数并发请求多次

前言

在一些项目里,我们可能有着大量的下拉框,而这些下拉框的数据就来源于我们后端接口返回的字典信息。于是,画风可能是这样的,每次下拉,你都需要请求一次字典接口拿到这些数据,于是每次组件刷新都会重复请求接口,造成性能上的浪费,如下图所示:

image.png

那么,我们可不可以把这些字典值缓存起来,只在第一次加载时请求一次呢?

使用vuex缓存字典数据

Vue项目中,我们要实现数据的缓存,自然要考虑到VuexPinia状态管理了。

思路是这样的:每个字典肯定有一个key,也就是其名字,每次拿字典值先从状态管理中寻找字典的key,如果找不到或者数据为空,我们就请求接口,响应后先把数据处理后存放在状态管理后再返回;当第二次请求时,自然地就从状态管理中取值而不是再次请求接口了。

新建测试项目,后台使用koa返回简单的字典值:

image.png

前端为Vue3+Vuex,使用Element-Plus组件库中的Select下拉组件,此下拉组件需要的数据格式如下:

[{label:"",value:""}]

Vuex中相关代码为:

const store =createStore({state:{dicData:{}},mutations:{getDic(state:any,key:string){return state.dicData[key]},setDic(state:any,data:{key:string;list:any[]}){const {key,list} =data;state.dicData[key]=list}},actions:{async GET_DIC(context:any,payload:any){const {key} = payloadif(context.state.dicData[key]){return context.state.dicData[key]} else{const data =(await getDicData(key)).dataconst list = data.map(item=>({value: item.key || item.code,label: item.value || item.name}))context.commit('setDic',{key:key,list:list});return list}}}
})

 

在actions的GET_DIC方法中,我们根据传入的key先从state中的dicData取出字典值,取不到后才请求接口getDicData拿到值,做数据处理后,先通过mutation的setDic方法设置字典数据再返回。

调用如下:

 store.dispatch("GET_DIC",{key:"fruit"}).then(res=>{options.value=res;})

这样,无论组件怎么刷新接口始终只调用一次,节省了等待时间和带宽。

如果后端接口没有这么规范,每一个字典都单独做了一个接口,也可以利用swtich,根据不同的key单独写处理数据的逻辑,最终在dicData的值均是形如以下的数据格式就好了。

dicData:{"fruit":[{label:"苹果",value:101}],"class":[{label:"一年级一班",value:201}]
}

Pinia的实现

export const useSelectStore =defineStore('select',{state:()=>{return{dicData:{}}},actions:{setDic(key:string,list:any[]){this.dicData[key]=list;},async getDic(key:string){console.log(this.dicData)if(this.dicData[key]){return this.dicData[key]} else{const data =(await getDicData(key)).data;const list = data.map(item=>({value: item.key || item.code,label: item.value || item.name}));this.setDic(key,list);return list;}}}
})

调用

const selectStore= useSelectStore();
selectStore.getDic(props.requestKey).then(res=>{options.value=res;})

Pinia代码上差不了太多,不过其本身的确比Vuex简洁一些。

同时渲染造成的请求并发问题

评论区有小伙伴说到了万一同时渲染会发起多个一样的请求,也就是请求并发的问题。如图所示,页面有四个班级列表的下拉。渲染该页面则每个下拉都会发起一个请求,即:

image.png

可以看到,班级的字典数据请求共有4次,违背了我们设计的初衷。那么,我们如何解决呢?就要对接口本身做缓存了,而这个缓存方案也很简单,我们这块只需要对字典数据的接口单独缓存,使用Promise就够了。

先上代码(以Pinia为例):

const cacheMap={};
​
export const useSelectStore =defineStore('select',{state:()=>{return{dicData:{}}},actions:{setDic(key:string,list:any[]){this.dicData[key]=list;},getDic(key:string){// console.log(this.dicData)if(this.dicData[key]){return new Promise((resolve,reject)=>{resolve(this.dicData[key])})} else{// return new Promise((resolve,reject)=>{//     getDicData(key).then(res=>{//         const data =res.data;//         const list = data.map(item=>({//             value: item.key || item.code,//             label: item.value || item.name//         }));//         this.setDic(key,list);//         resolve(list);//     })// })//添加接口并发缓存处理if((cacheMap?.[key]?.length ?? 0)==0){cacheMap[key]=[];getDicData(key).then(res=>{const data =res.data;while(cacheMap[key].length){const list = data.map(item=>({value: item.key || item.code,label: item.value || item.name}));this.setDic(key,list);const resolve = cacheMap[key].shift();resolve[0](list)}})}return new Promise((resolve,reject)=>{cacheMap[key].push([resolve,reject]);})}}}
})
​

 

cacheMap为全局的缓存对象,其每个属性key为字典的key,每次请求返回一个promise,并将resolvereject回调存储下来。对于cacheMap[key],其数组为空时,可知是首次请求,此时调用接口获取数据。由于接口请求也是异步,实例化Promise的语句是同步的,当请求响应前所有的resolvereject回调已经缓存。我们调用所有的resolve完成所有的promise并清空数组,就实现了简单的接口缓存。

image.png

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/27265.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# PaddleDetection 版面分析

效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Extensions; using Sdcb.PaddleDetection; using Sdcb.PaddleInference; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Lin…

目前Java后端就业前景怎么样?

前言 并不乐观,看看现在的就业形式就知道了,基本上是僧多粥少的情况,你可能会看到很多编程语言排行榜或者流行榜中Java的排名很高,如同下面这种: 看排名确实可以粗略的得知语言当下的流行度、使用率,但是它…

Redis如何实现Session存储

在Redis中实现Session存储,主要有两种方式:使用Spring Session和手动存储。 使用Spring Session:Spring Session是Spring框架提供的一个模块,用于简化Session管理,并将Session数据存储到外部数据存储中,如Redis。使用Spring Session,你只需要在Spring Boot项目中添加相应…

springBoot的配置文件

目录 配置文件的格式 1. 配置项的分类和中文支持 2. properties 配置文件 读取配置文件 优缺点分析 3. yml 配置文件 读取配置文件 优缺点分析: 4. 多个配置文件 5. properties 和 yml 的对比 在 springBoot 中很多重要的数据是需要通过配置文件进行配置…

并发——什么是线程,什么是进程

文章目录 1.1. 何为进程?1.2. 何为线程? 1.1. 何为进程? 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。 在 Java 中,当我们启动 main 函数时…

npm install 安装慢的问题处理

原因 npm install 默认使用的安装镜像时国外的镜像,国内使用会受到网络的限制。 解决方案 更换网络更换npm的安装镜像为国内,比如: npm config set registry https://registry.npm.taobao.org

qt源码---事件系统之QCoreApplication

上一节分析了qt和windows系统之间的消息的传递,本节着重看一下,qt内部的事件是如何传递的? 1.sendEvent函数 在使用的自定义事件时,有时需要手动抛出一个事件,常用的方式有2种,其一时阻塞式的sendEvent函…

Kubernetes(K8s)从入门到精通系列之十:使用 kubeadm 创建一个高可用 etcd 集群

Kubernetes K8s从入门到精通系列之十:使用 kubeadm 创建一个高可用 etcd 集群 一、etcd高可用拓扑选项1.堆叠(Stacked)etcd 拓扑2.外部 etcd 拓扑 二、准备工作三、建立集群1.将 kubelet 配置为 etcd 的服务管理器。2.为 kubeadm 创建配置文件…

微服务间消息传递

微服务间消息传递 微服务是一种软件开发架构,它将一个大型应用程序拆分为一系列小型、独立的服务。每个服务都可以独立开发、部署和扩展,并通过轻量级的通信机制进行交互。 应用开发 common模块中包含服务提供者和服务消费者共享的内容provider模块是…

有关OpenBSD, NetBSD, FreeBSD -- 与GPT对话

1 介绍一下 - OpenBSD, NetBSD, FreeBSD 当谈论操作系统时,OpenBSD、NetBSD和FreeBSD都是基于BSD(Berkeley Software Distribution)的操作系统,它们各自是独立开发的,并在BSD许可下发布。这些操作系统有很多共同点,但也有一些差异。以下是对它们的简要介绍: OpenBSD: O…

阿里云翻译使用

代码阿里云翻译包 代码 package xxx.yyy.zzz;import com.aliyun.alimt20181012.models.TranslateGeneralResponse; import org.apache.commons.lang3.StringUtils;import java.util.*; import java.util.stream.Collectors;public class AlibabaCloudTranslation {//默认idpub…

K8S系列文章 之 编写自动化部署K8S脚本

介绍 通过ansible脚本shell实现自动化部署k8s基础集群(v1.25.0) 部署结构 1. 通过二进制部署包镜像安装k8s集群、目录etcd节点只支持1-3个节点、最多三个etcd节点 2. 因k8s版本相对较新、需要升级内核来支持后台程序、当前版本只支持Cento7,内核版本(5.19.4-1.el7…

Object Map 的相互转换

学生业务对象定义&#xff1a;Student Student student new Student(); student.setId(1L); student.setName("令狐冲") student.setAge(10) 第一种&#xff1a;通过Alibaba Fastjson实现 pom.xml 文件依赖 <dependency><groupId>com.alibaba</g…

【EI/SCOPUS征稿】第三届电子通信与计算机科学技术国际学术会议(ECCST 2023)

第三届电子通信与计算机科学技术国际学术会议&#xff08;ECCST 2023&#xff09; 2023 3rd International Conference on Electronic Communication,Computer Science and Technology 2023年电子通信与计算机科学技术国际学术会议定于2023年9月15-17日在中国上海举行。会议旨…

培训报名小程序报名功能开发

目录 1 创建页面2 新建URL参数3 课程详细信息4 报名数据源创建5 报名信息功能开发6 设置页面跳转7 最终实现的效果总结 在培训报名小程序中&#xff0c;我们已经开发了首页和列表页。在列表页点击报名时就跳转到报名页面&#xff0c;先看我们的原型 报名页分为两个部分&#x…

供应链售后服务自动化,利用软件机器人将数据整合提升效率

随着供应链管理的不断发展&#xff0c;售后服务的重要性也日益凸显。良好的售后服务不仅可以提高客户满意度&#xff0c;还能增强品牌形象和忠诚度。然而&#xff0c;传统的供应链售后服务往往存在繁琐的操作、低效率和易出错的问题。为了解决这一挑战&#xff0c;越来越多的企…

ABAQUS启动GPU加速计算

文章目录 系统说明CUDA安装安装cuDNNABAQUS设置Lamb波压电仿真 系统说明 基于笔记本电脑&#xff0c;RTX4060&#xff0c;win11系统。 ABAQUS的有限元求解器是基于CPU的&#xff0c;但是它也支持使用GPU进行加速计算。仅支持隐式求解器standard。显示求解器explicit不能用。 …

Golang之路---04 并发编程——WaitGroup

WaitGroup 为了保证 main goroutine 在所有的 goroutine 都执行完毕后再退出&#xff0c;前面使用了 time.Sleep 这种简单的方式。 由于写的 demo 都是比较简单的&#xff0c; sleep 个 1 秒&#xff0c;我们主观上认为是够用的。 但在实际开发中&#xff0c;开发人员是无法…

【大数据】Flink 详解(二):核心篇 Ⅰ

Flink 详解&#xff08;二&#xff09;&#xff1a;核心篇 Ⅰ 14、Flink 的四大基石是什么&#xff1f; ​ Flink 的四大基石分别是&#xff1a; Checkpoint&#xff08;检查点&#xff09;State&#xff08;状态&#xff09;Time&#xff08;时间&#xff09;Window&#xff…

《面试1v1》ElasticSearch架构设计

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…