Vue 3 中处理多并发请求部分失败,应使用 Promise.allSettled 获取各请求状态,配合 Axios 响应拦截器统一错误分类(network/auth/server/client),并结合 fallback 数据、缓存兜底及手动重试机制保障用户体验。

Vue 3 中处理多个并发请求时部分失败的情况,关键不是避免失败,而是让失败不中断整体流程、不掩盖有效数据、不导致界面异常。推荐用 Promise.allSettled 替代 Promise.all,并配合拦截器和响应结构统一处理。
用 Promise.allSettled 获取全部结果状态
Promise.all 一错即停,不适合容错场景;Promise.allSettled 会等待所有请求结束,无论成功或失败,返回每个请求的 { status, value | reason } 对象,便于分别处理。
- 封装三个请求函数(返回 axios Promise):
// 示例:用户、订单、通知数据
const fetchUser = () => axios.get('/api/user');
const fetchOrders = () => axios.get('/api/orders');
const fetchNotices = () => axios.get('/api/notices');
- 并发执行并逐个判断结果:
const results = await Promise.allSettled([
fetchUser(),
fetchOrders(),
fetchNotices()
]);
// 分别提取成功/失败项
const [userRes, orderRes, noticeRes] = results;
if (userRes.status === 'fulfilled') {
userInfo.value = userRes.value.data;
} else {
console.warn('用户加载失败', userRes.reason);
// 可设默认值或保留旧数据
}
if (orderRes.status === 'fulfilled') {
orders.value = orderRes.value.data;
} else {
showToast('订单列表加载异常,部分功能受限');
}
在 Axios 响应拦截器中标准化错误分类
即使用了 allSettled,后端返回的 401、500、网络超时等仍需统一识别。建议在响应拦截器里把错误归为几类,并挂载到 error 对象上,方便后续判断。
- 在 request.ts 的响应拦截中补充逻辑:
// 检查是否为网络层失败(无 response)
if (!error.response) {
error.type = 'network'; // 如断网、DNS 失败、跨域拒绝
error.message = '网络不可用,请检查连接';
}
// 检查 HTTP 状态码
else if (error.response.status === 401) {
error.type = 'auth';
error.message = '登录已过期,请重新登录';
} else if (error.response.status >= 500) {
error.type = 'server';
error.message = '服务暂时异常,请稍后再试';
} else {
error.type = 'client';
error.message = error.response.data?.message || '请求参数有误';
}
审查 Vue 管理后台的变更请求(Vue 2 + Element UI,Vue 3 + Element Plus)。重点关注最小化变更实现、上线风险检查以及回归检查清单生成。
- 这样在 allSettled 的 catch 分支里就能按 type 区分处理,比如只对 'server' 类型弹 toast,对 'auth' 跳转登录页,对 'network' 显示重试按钮。
给关键请求加 fallback 数据或缓存兜底
部分失败时,用户感知最差的是“白屏”或“空列表”。可结合 ref 或 reactive 提前设置默认值,或读取本地缓存作为临时 fallback。
- 例如用户信息加载失败,但上次成功数据还在 localStorage 中:
const cachedUser = JSON.parse(localStorage.getItem('last_user') || '{}');
if (userRes.status === 'fulfilled') {
userInfo.value = userRes.value.data;
localStorage.setItem('last_user', JSON.stringify(userInfo.value));
} else if (Object.keys(cachedUser).length > 0) {
userInfo.value = cachedUser;
showToast('使用本地缓存数据,最新信息稍后同步');
}
- 对非敏感数据(如公告、配置项),甚至可以设置短时内存缓存(Map + 时间戳),避免重复失败。
失败请求支持手动重试机制
allSettled 后,可把失败项单独拎出来,提供“重试单个”或“重试全部失败项”的能力,而不是整页刷新。
- 记录失败请求的函数和索引,点击重试时重新调用对应函数:
const failedRequests = results
.map((r, i) => ({ r, i }))
.filter(({ r }) => r.status === 'rejected')
.map(({ r, i }) => ({ fn: [fetchUser, fetchOrders, fetchNotices][i], index: i }));
// 重试第 0 个失败项
const retryOne = async (item) => {
try {
const res = await item.fn();
// 更新对应位置的数据
updateByIndex(item.index, res.data);
} catch (err) {
console.error('重试仍失败', err);
}
};
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









