
本文介绍如何通过合理使用 `async/await` 替代 `.then()` 链式调用,提升异步代码的可读性与可维护性,并给出符合最佳实践的重构示例。
在 JavaScript 异步编程中,.then().catch() 链虽然功能完备,但嵌套过深或逻辑复杂时容易导致“回调地狱”式的可读性下降。而 async/await 语法以同步风格书写异步逻辑,显著增强代码的线性表达力和语义清晰度。
你当前的写法:
const apiCall = async() => {
const response = await axios.get("URL");
return response;
}
apiCall().then(res => {
console.log(res.data);
});虽已使用 async/await 封装请求,但在调用端仍依赖 .then(),未能充分发挥其优势。更推荐的方式是全程统一使用 async/await,包括调用层:
✅ 推荐重构方案(简洁、语义明确、错误可捕获):
const apiCall = async () => {
try {
const { data } = await axios.get("URL");
return data; // 直接解构并返回业务数据,避免上层重复访问 .data
} catch (error) {
console.error("API 请求失败:", error.message);
throw error; // 保留错误,便于上层处理(如重试、兜底 UI)
}
};
const fetchData = async () => {
try {
const data = await apiCall();
console.log(data);
return data;
} catch (error) {
// 可在此处添加特定业务错误处理逻辑
throw error;
}
};
// 正确调用方式(必须在 async 上下文中)
fetchData().catch(console.error);
// 或在顶层模块中使用 IIFE(适用于非模块环境或 script 标签)
(async () => {
try {
const result = await fetchData();
console.log("获取成功:", result);
} catch (err) {
console.warn("最终未捕获的异常:", err);
}
})();⚠️ 注意事项:
- await 只能在 async 函数内部使用,因此 console.log(fetchData()) ❌ 是错误的——它会打印一个 Promise 对象,而非实际数据;
- 始终包裹 await 调用在 try/catch 中,避免未捕获的 Promise rejection 导致静默失败;
- 接口函数(如 apiCall)应聚焦职责:封装请求 + 统一错误处理 + 返回干净的数据结构(如直接返回 data),降低消费者耦合度;
- 若需复用底层 Promise(如并发请求),可保留 axios.get(...) 的原始 Promise 返回,但此时函数不应声明为 async,否则会多一层不必要的 Promise 包装。
总结:可读性提升的关键不在于“是否用了 await”,而在于统一范式、职责分离、错误显式化、数据标准化。从 .then() 迁移至 async/await 不仅是语法糖替换,更是异步流程设计思维的升级。










