async/await 重构嵌套 fetch 的核心是将回调地狱转为线性同步风格代码,支持顺序执行、并行请求(Promise.all)、统一封装(apiFetch)及条件分支处理,兼顾可读性、错误处理与依赖逻辑。

用 async/await 重构嵌套的 fetch 请求,核心是把“回调地狱”变成线性、可读、易维护的同步风格代码,同时保留错误处理和依赖逻辑。
把嵌套 then 链转为 await 顺序调用
传统嵌套写法容易层层缩进、难以追踪数据流向。改成 async/await 后,每个请求像写同步代码一样自然执行:
✅ 正确示例(按顺序获取用户 → 获取其订单 → 获取订单商品):
async function getUserOrderDetails(userId) {
try {
const userRes = await fetch(`/api/users/${userId}`);
if (!userRes.ok) throw new Error(`用户获取失败: ${userRes.status}`);
const user = await userRes.json();
const orderRes = await fetch(`/api/orders?userId=${user.id}`);
if (!orderRes.ok) throw new Error(`订单获取失败: ${orderRes.status}`);
const orders = await orderRes.json();
if (orders.length === 0) return { user, orders: [] };
const productRes = await fetch(`/api/products?id=${orders[0].productId}`);
if (!productRes.ok) throw new Error(`商品获取失败: ${productRes.status}`);
const product = await productRes.json();
return { user, order: orders[0], product };
} catch (err) {
console.error('请求链中断:', err.message);
throw err;
}
}
并行请求用 Promise.all + await 提升效率
如果多个请求无依赖关系(比如同时拉取用户信息、通知数、未读消息),不该串行等待,而应并发发起:
立即学习“Java免费学习笔记(深入)”;
- 用
Promise.all包裹多个fetch调用,再await等待全部完成 - 每个
fetch仍需单独await解析响应体(json()也是 Promise) - 注意:
Promise.all任一失败则整体 reject,如需容错可用Promise.allSettled
✅ 并行示例:
async function loadDashboardData(userId) {
const [userRes, notifyRes, messageRes] = await Promise.all([
fetch(`/api/users/${userId}`),
fetch(`/api/notifications/count?userId=${userId}`),
fetch(`/api/messages/unread?userId=${userId}`)
]);
const [user, notifyCount, unreadMessages] = await Promise.all([
userRes.json(),
notifyRes.json(),
messageRes.json()
]);
return { user, notifyCount, unreadMessages };
}
封装通用 fetch 函数,统一错误与配置
重复写 if (!res.ok) 和 res.json() 很冗余。建议封装一个健壮的 apiFetch:
- 自动检查 HTTP 状态、抛出语义化错误
- 默认加
Content-Type: application/json和认证 token - 支持传入自定义
options覆盖默认行为
✅ 封装示例:
async function apiFetch(url, options = {}) {
const token = localStorage.getItem('auth_token');
const config = {
headers: {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` })
},
...options
};
const res = await fetch(url, config);
if (!res.ok) {
const errorData = await res.json();
throw new Error(errorData.message || `HTTP ${res.status}`);
}
return res.json();
}
// 使用时干净利落:
async function updateUserProfile(data) {
const user = await apiFetch('/api/profile', {
method: 'PATCH',
body: JSON.stringify(data)
});
return user;
}
处理条件分支和可选请求(避免 undefined await)
有些请求是否执行取决于前序结果(例如只有管理员才拉取日志)。别在 await 前放未定义值,要用条件判断包裹:
- 用
if控制是否发起请求,而不是await maybeFetch() - 对可能为空的数据做防御性检查(如
user?.role === 'admin') - 把可选请求的结果设为
null或默认值,保持返回结构稳定
✅ 条件请求示例:
async function getProfileWithLogs(userId) {
const user = await apiFetch(`/api/users/${userId}`);
let logs = null;
if (user.role === 'admin') {
logs = await apiFetch(`/api/logs?userId=${userId}&limit=10`);
}
return { user, logs };
}


















