接口调用失败时返回备用数据,核心是用try...catch或.catch()捕获错误并在错误分支返回预设本地数据;可结合localStorage缓存实现“上一次成功数据”降级,支持时间戳过期判断;还可封装safeFetch通用函数,支持自定义fallback逻辑。

接口调用失败时返回备用数据,核心是用 try...catch 或 .catch() 捕获错误,并在错误分支中返回预设的本地数据或兜底逻辑。
使用 async/await + try/catch 返回静态备用数据
适合简单场景,比如列表页加载失败时展示上次缓存的数据或默认空数组:
async function fetchUserData() {
try {
const res = await fetch('/api/user');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.warn('接口请求失败,启用备用数据', err);
// 返回本地定义的备用数据(可来自内存、localStorage 或硬编码)
return {
id: -1,
name: '游客',
avatar: '/assets/avatar-default.png',
permissions: []
};
}
}结合 localStorage 缓存实现“上一次成功数据”降级
用户上次成功加载的数据往往比纯静态兜底更合理,尤其对非实时性要求高的页面:
- 请求成功后,立即将结果存入
localStorage(注意控制大小和过期) - 请求失败时,优先读取
localStorage中的缓存数据 - 可加时间戳判断是否过期,过期则返回更保守的默认值
function getCachedData(key) {
const item = localStorage.getItem(key);
if (!item) return null;
const { data, timestamp } = JSON.parse(item);
// 10分钟内缓存有效
if (Date.now() - timestamp < 10 * 60 * 1000) {
return data;
}
localStorage.removeItem(key);
return null;
}
<p>async function fetchWithCache() {
try {
const res = await fetch('/api/config');
const data = await res.json();
localStorage.setItem('config-cache', JSON.stringify({
data,
timestamp: Date.now()
}));
return data;
} catch (err) {
const cached = getCachedData('config-cache');
return cached ?? { theme: 'light', language: 'zh-CN' };
}
}为不同错误类型提供差异化降级策略
网络超时、404、500、JSON 解析失败等应区别对待:
立即学习“Java免费学习笔记(深入)”;
- 网络错误(
TypeError: Failed to fetch)→ 返回离线可用的完整备用数据 - 404 → 可降级为“资源不存在”的轻量提示对象,避免渲染异常
- 500 / 502 → 返回带重试按钮的占位数据,或引导用户手动刷新
- 解析失败 → 检查响应体是否为空或非 JSON,再 fallback
async function fetchWithTypedFallback() {
try {
const res = await fetch('/api/profile');
if (res.status === 404) {
return { status: 'not-found', user: null };
}
if (!res.ok) {
throw Object.assign(new Error(`API error: ${res.status}`), { status: res.status });
}
return await res.json();
} catch (err) {
if (err.name === 'TypeError' || err.message.includes('fetch')) {
// 网络断开
return { status: 'offline', user: getOfflineUser() };
}
if (err.status === 500 || err.status === 502) {
return { status: 'server-error', retryable: true };
}
// 兜底
return { status: 'unknown-error', user: getDefaultUser() };
}
}封装通用降级请求函数,支持传入备用数据生成器
避免每个接口都写重复逻辑,抽成可复用工具:
async function safeFetch(url, options = {}, fallbackFn = () => ({})) {
try {
const res = await fetch(url, options);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error(`[safeFetch] failed for ${url}:`, err);
return typeof fallbackFn === 'function' ? fallbackFn(err) : fallbackFn;
}
}
<p>// 使用示例
const user = await safeFetch('/api/user', {}, () => ({
id: 0,
name: '加载中...',
isOnline: false
}));


















