当然,以下是《JavaScript 异步编程 Async/Await 使用详解:从原理到最佳实践》的完整内容,涵盖基础语法、实现原理、异常处理、并发控制、最佳实践、性能建议等方面,并穿插示例与注意事项,适合中高级开发者系统学习。
📘 目录
- 什么是异步编程?
- Promise 简要回顾
- Async/Await 是什么?
- Async 函数的工作机制
- Await 表达式详解
- 异常处理方式
- 并发与串行控制技巧
- Async/Await 的最佳实践
- 常见陷阱与误区
- 性能与调试建议
- 总结与参考资料
1. 什么是异步编程?
异步编程是处理耗时任务(如网络请求、文件读写、计时器)的主要方式,防止阻塞主线程。
传统方案如:
setTimeout(() => {
console.log("Hello after 1s");
}, 1000);
回调地狱(callback hell)令人头痛,因此引入了 Promise,再演进为更优雅的 async/await。
2. Promise 简要回顾
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("data loaded"), 1000);
});
}
fetchData().then(data => console.log(data)).catch(err => console.error(err));
但 .then().then().catch()
可读性差,异常处理复杂。
3. Async/Await 是什么?
Async/Await 是基于 Promise 的语法糖,使异步代码像同步那样书写。
示例
async function load() {
const data = await fetchData();
console.log(data);
}
async
函数始终返回一个Promise
await
表达式暂停函数执行,等待 Promise 结果
4. Async 函数的工作机制
async function foo() {
return 42;
}
foo().then(console.log); // 输出 42
本质上等价于:
function foo() {
return Promise.resolve(42);
}
即使返回普通值也会自动包装为 Promise
。
5. Await 表达式详解
✅ 正确使用
const response = await fetch(url);
const data = await response.json();
🚫 错误用法:顶级不能直接 await(ES2022 顶级 await 支持后例外)
const result = await someAsyncFunc(); // ⛔ 报错
应包在 async 函数中:
(async () => {
const result = await someAsyncFunc();
})();
6. 异常处理方式
Async/Await 异常处理推荐使用 try...catch
:
async function loadData() {
try {
const res = await fetch("https://api.example.com/data");
const json = await res.json();
console.log(json);
} catch (err) {
console.error("请求失败:", err);
}
}
你也可以使用 .catch()
:
loadData().catch(console.error);
7. 并发与串行控制技巧
❌ 串行(性能差)
const a = await fetch(url1);
const b = await fetch(url2); // 等待 a 结束后才执行
✅ 并发执行(推荐)
const [a, b] = await Promise.all([fetch(url1), fetch(url2)]);
处理失败也要继续执行
const results = await Promise.allSettled([fetchA(), fetchB()]);
8. Async/Await 的最佳实践
✅ 封装异步逻辑
async function getUser() {
const res = await fetch("/api/user");
return await res.json();
}
✅ 显式处理错误
try {
const data = await getData();
} catch (e) {
logger.error(e);
}
✅ 使用 loading 状态
async function load() {
loading = true;
try {
const res = await fetchData();
data = res;
} finally {
loading = false;
}
}
9. 常见陷阱与误区
❌ await forEach 无效!
[1, 2, 3].forEach(async n => {
await delay(n * 1000);
console.log(n);
});
这是错误的,因为 forEach
不等待异步。
✅ 使用 for...of
:
for (const n of [1, 2, 3]) {
await delay(n * 1000);
console.log(n);
}
10. 性能与调试建议
✅ 并发处理优化
- 多请求用
Promise.all
或Promise.allSettled
- 不相关任务并行执行,避免 await 阻塞
✅ 异步调试建议
- 使用
--inspect
启动 Node.js 或 Chrome DevTools - 加
debugger
可断点 async 函数 - 捕捉全局未处理异常:
window.addEventListener("unhandledrejection", e => {
console.error("未处理的 Promise 错误:", e.reason);
});
11. 总结与参考资料
✅ Async/Await 优势
- 异步流程同步写法
- 更清晰的异常处理
- 可读性强,可维护性高
⚠️ 注意
- 仅能用于异步函数内
- 使用
forEach
或map
配合await
时要小心 - 注意性能陷阱,适当并发处理
发表回复