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

这篇具有很好参考价值的文章主要介绍了Vue缓存字典值减少网络请求次数,解决同样参数并发请求多次。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

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

Vue缓存字典值减少网络请求次数,解决同样参数并发请求多次,vue.js,前端,javascript

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

使用vuex缓存字典数据

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

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

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

Vue缓存字典值减少网络请求次数,解决同样参数并发请求多次,vue.js,前端,javascript

前端为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} = payload
            if(context.state.dicData[key]){
                return context.state.dicData[key]
            } else{
                const data =(await getDicData(key)).data
                const list = data.map(item=>({
                    value: item.key || item.code,
                    label: item.value || item.name
                }))
                context.commit('setDic',{key:key,list:list});
                return list
            }
        }
    }
})

 文章来源地址https://www.toymoban.com/news/detail-632160.html

在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简洁一些。

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

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

Vue缓存字典值减少网络请求次数,解决同样参数并发请求多次,vue.js,前端,javascript

Vue缓存字典值减少网络请求次数,解决同样参数并发请求多次,vue.js,前端,javascript

可以看到,班级的字典数据请求共有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并清空数组,就实现了简单的接口缓存。

Vue缓存字典值减少网络请求次数,解决同样参数并发请求多次,vue.js,前端,javascript

 

到了这里,关于Vue缓存字典值减少网络请求次数,解决同样参数并发请求多次的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包