Vue开发中如何全局存储服务端数据避免重复发起请求
问题原因
你当前的实现存在两个导致重复请求的问题:
- 每个组件的
created生命周期都主动触发了user/updateUseraction updateUseraction 内部没有判断是否已经拉取过用户数据,每次调用都会直接发起新请求
修复方案
方案1:最简修改(推荐新手使用)
直接去掉所有组件created中调用this.$store.dispatch("user/updateUser")的代码,只在项目入口(如main.js)全局调用一次即可,Vuex的状态是全局共享的,一次拉取所有组件都能访问:
// main.js import { createApp } from 'vue' import App from './App.vue' import store from './store' // 全局仅初始化拉取一次用户数据 store.dispatch('user/updateUser') createApp(App).use(store).mount('#app')
方案2:给Action加请求拦截(更健壮,兼容按需拉取场景)
如果你的业务存在需要按需触发拉取的场景,可以直接修改userModule的updateUser action,加入已有数据直接返回的逻辑,即使多次调用也不会重复发请求。
首先建议把state的current初始值改为null,方便非空判断:
// userModule.js import axios from 'axios'; // 用于存储 pending 状态的请求,避免并发调用时重复发起请求 let pendingUserRequest = null export const userModule = { state: () => ({ current: null, // 初始改为null,判断更准确 }), getters: { getUser(state) { return state.current }, }, mutations: { setUser(state, user) { state.current = user }, }, actions: { async updateUser({state, commit}) { // 已有用户数据,直接返回不发请求 if (state.current) return state.current // 已有正在进行的请求,直接复用该请求 if (pendingUserRequest) return pendingUserRequest try { pendingUserRequest = axios.get('/office/api/me'); const response = await pendingUserRequest; commit('setUser', response.data); return response.data } catch (e) { console.log(e); alert('Error'); // 请求失败清空缓存,允许下次重试 pendingUserRequest = null throw e } }, }, namespaced: true, }
修改完成后即使你保留组件内的dispatch调用,也不会出现重复请求的问题。
内容的提问来源于stack exchange,提问作者Николай
相关产品推荐
相关产品推荐

