面试题答案
一键面试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 };
}
}