MST

星途 面试题库

面试题:Vue3的Vuex下优化网络请求状态管理以应对高并发场景

在一个高并发的Vue3应用场景下,多个网络请求可能同时发起,使用Vuex管理这些请求状态时可能会出现状态混乱等问题。请详细说明如何优化Vuex的设计来准确且高效地管理高并发网络请求状态,包括但不限于如何处理状态冲突、队列化请求等,并给出相应的代码实现方案。
36.6万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

1. 使用唯一标识符

为每个网络请求生成唯一标识符(例如 uuid),在 Vuex 中以该标识符为键来管理请求状态。这样可以避免多个请求状态之间的混淆。

代码实现

import { v4 as uuidv4 } from 'uuid';

// 在组件中发起请求时
const requestId = uuidv4();
this.$store.dispatch('fetchData', { requestId, url: 'your-url' });

// Vuex actions
actions: {
  async fetchData({ commit }, { requestId, url }) {
    commit('SET_REQUEST_STATUS', { requestId, status: 'loading' });
    try {
      const response = await axios.get(url);
      commit('SET_REQUEST_STATUS', { requestId, status:'success', data: response.data });
    } catch (error) {
      commit('SET_REQUEST_STATUS', { requestId, status: 'error', error });
    }
  }
},

// Vuex mutations
mutations: {
  SET_REQUEST_STATUS(state, { requestId, status, data, error }) {
    state.requests[requestId] = { status, data, error };
  }
},

// Vuex state
state: {
  requests: {}
}

2. 队列化请求

当一个请求正在处理时,将后续相同类型或针对相同资源的请求放入队列,等待当前请求完成后依次处理。

代码实现

// Vuex actions
actions: {
  async fetchData({ commit, state }, { url }) {
    // 检查是否有相同请求正在处理
    const existingRequest = Object.values(state.requests).find(req => req.status === 'loading' && req.url === url);
    if (existingRequest) {
      // 放入队列
      state.requestQueue.push({ url });
      return;
    }
    const requestId = uuidv4();
    commit('SET_REQUEST_STATUS', { requestId, status: 'loading', url });
    try {
      const response = await axios.get(url);
      commit('SET_REQUEST_STATUS', { requestId, status:'success', data: response.data });
      // 处理队列中的请求
      if (state.requestQueue.length > 0) {
        const nextRequest = state.requestQueue.shift();
        this.$store.dispatch('fetchData', nextRequest);
      }
    } catch (error) {
      commit('SET_REQUEST_STATUS', { requestId, status: 'error', error });
    }
  }
},

// Vuex mutations
mutations: {
  SET_REQUEST_STATUS(state, { requestId, status, data, error, url }) {
    state.requests[requestId] = { status, data, error, url };
  }
},

// Vuex state
state: {
  requests: {},
  requestQueue: []
}

3. 使用 Promise.allSettled 处理并发请求

如果有多个相互独立的请求需要并发处理,可以使用 Promise.allSettled 来确保所有请求都处理完成,并统一更新 Vuex 状态。

代码实现

// Vuex actions
actions: {
  async fetchMultipleData({ commit }) {
    const requests = [
      axios.get('url1'),
      axios.get('url2'),
      axios.get('url3')
    ];
    const results = await Promise.allSettled(requests);
    const newState = results.map((result, index) => {
      if (result.status === 'fulfilled') {
        return { status:'success', data: result.value.data };
      } else {
        return { status: 'error', error: result.reason };
      }
    });
    commit('SET_MULTIPLE_REQUEST_STATUS', newState);
  }
},

// Vuex mutations
mutations: {
  SET_MULTIPLE_REQUEST_STATUS(state, newState) {
    state.multipleRequests = newState;
  }
},

// Vuex state
state: {
  multipleRequests: []
}

4. 处理状态冲突

通过上述的唯一标识符和队列化请求,可以有效减少状态冲突。此外,在更新状态时,可以添加版本号机制。每次请求前,状态版本号加一,在更新状态时,检查当前版本号是否与预期一致,避免旧状态覆盖新状态。

代码实现

// Vuex state
state: {
  requests: {},
  version: 0
},

// Vuex actions
actions: {
  async fetchData({ commit, state }, { url }) {
    const requestId = uuidv4();
    const currentVersion = state.version++;
    commit('SET_REQUEST_STATUS', { requestId, status: 'loading', url, version: currentVersion });
    try {
      const response = await axios.get(url);
      // 检查版本号
      if (state.requests[requestId].version === currentVersion) {
        commit('SET_REQUEST_STATUS', { requestId, status:'success', data: response.data });
      }
    } catch (error) {
      // 检查版本号
      if (state.requests[requestId].version === currentVersion) {
        commit('SET_REQUEST_STATUS', { requestId, status: 'error', error });
      }
    }
  }
},

// Vuex mutations
mutations: {
  SET_REQUEST_STATUS(state, { requestId, status, data, error, url, version }) {
    state.requests[requestId] = { status, data, error, url, version };
  }
}