MST
星途 面试题库

面试题:Vue项目复杂场景下网络请求缓存机制与数据一致性的保障

在一个大型Vue项目中,存在多个组件会发起相同接口但不同参数的请求,且这些组件可能处于不同的生命周期阶段。例如一个电商项目,商品列表页和商品详情页都会请求商品基本信息接口,但列表页可能只需要部分字段,详情页需要完整信息。同时,后端数据可能会不定期更新。请设计一套完整的网络请求缓存机制,确保各个组件获取到的数据一致性,并且在数据更新时能及时通知到相关组件,详细阐述设计思路、涉及到的技术点及关键代码实现。
38.8万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 集中式缓存管理:使用一个全局的缓存对象来存储所有请求的结果,确保不同组件对相同请求能获取一致数据。
  2. 缓存标识:根据请求的URL和参数生成唯一的缓存标识,以此来判断缓存中是否已有对应数据。
  3. 数据更新监听:通过后端推送机制(如WebSocket)或轮询方式,检测数据是否更新。若更新,清除对应缓存,并通知相关组件重新请求数据。
  4. 组件订阅:组件订阅特定数据的更新,当数据变化时,组件能收到通知并重新获取最新数据。

涉及技术点

  1. Vuex:用于管理全局状态,存储缓存数据。通过Vuex的状态管理,不同组件可以共享和访问缓存数据。
  2. Axios:用于发送网络请求。Axios可以方便地拦截请求和响应,进行缓存相关操作。
  3. WebSocket(可选):用于后端实时推送数据更新消息。若后端支持,使用WebSocket可以更高效地实现数据更新的实时通知。
  4. Object.freeze():用于冻结缓存数据,防止在组件中意外修改缓存数据。

关键代码实现

  1. Vuex模块定义
// store/modules/cache.js
const state = {
  cache: {}
};

const mutations = {
  SET_CACHE(state, { key, data }) {
    state.cache[key] = data;
  },
  CLEAR_CACHE(state, key) {
    if (state.cache[key]) {
      delete state.cache[key];
    }
  }
};

const actions = {
  async fetchData({ commit, state }, { url, params }) {
    const key = `${url}-${JSON.stringify(params)}`;
    if (state.cache[key]) {
      return state.cache[key];
    }
    try {
      const response = await axios.get(url, { params });
      commit('SET_CACHE', { key, data: response.data });
      return response.data;
    } catch (error) {
      console.error('Error fetching data:', error);
      throw error;
    }
  }
};

export default {
  namespaced: true,
  state,
  mutations,
  actions
};
  1. Axios拦截器
import axios from 'axios';
import store from '@/store';

axios.interceptors.request.use(config => {
  const { url, params } = config;
  const key = `${url}-${JSON.stringify(params)}`;
  const cachedData = store.state.cache.cache[key];
  if (cachedData) {
    return Promise.reject({ response: { data: cachedData } });
  }
  return config;
});

axios.interceptors.response.use(response => {
  const { url, params } = response.config;
  const key = `${url}-${JSON.stringify(params)}`;
  store.commit('cache/SET_CACHE', { key, data: response.data });
  return response;
});
  1. 组件使用
<template>
  <div>
    <button @click="fetchData">获取数据</button>
    <div v-if="data">{{ data }}</div>
  </div>
</template>

<script>
import { mapActions } from 'vuex';

export default {
  methods: {
  ...mapActions('cache', ['fetchData'])
  },
  async created() {
    try {
      const data = await this.fetchData({ url: '/api/product', params: { fields: 'name,price' } });
      this.data = data;
    } catch (error) {
      console.error('Error in component:', error);
    }
  }
};
</script>
  1. 数据更新通知(以WebSocket为例)
// 在main.js或单独的服务文件中
import store from '@/store';
const socket = new WebSocket('ws://your-server-url');

socket.onmessage = (event) => {
  const { url, params } = JSON.parse(event.data);
  const key = `${url}-${JSON.stringify(params)}`;
  store.commit('cache/CLEAR_CACHE', key);
  // 这里可以添加通知相关组件重新获取数据的逻辑,例如通过Vue的事件总线
};