异步编程的必要性
JavaScript 是单线程语言,这意味着同一时间只能执行一个任务。为了不阻塞主线程,异步编程成为了 JavaScript 的核心特性。
回调函数时代
最初的异步编程通过回调函数实现:
// 回调地狱示例
getData(function(a) {
getMoreData(a, function(b) {
getMoreData(b, function(c) {
getMoreData(c, function(d) {
// 嵌套越来越深...
});
});
});
});
Promise 的救赎
ES6 引入的 Promise 大大改善了异步代码的可读性:
// Promise 链式调用
getData()
.then(a => getMoreData(a))
.then(b => getMoreData(b))
.then(c => getMoreData(c))
.catch(error => console.error(error));
async/await 的优雅
ES2017 的 async/await 让异步代码看起来像同步代码:
// async/await 示例
async function fetchAllData() {
try {
const a = await getData();
const b = await getMoreData(a);
const c = await getMoreData(b);
return c;
} catch (error) {
console.error(error);
}
}
并发控制
当需要同时处理多个异步操作时,Promise 提供了强大的工具:
// 并行执行
const results = await Promise.all([
fetch('/api/users'),
fetch('/api/posts'),
fetch('/api/comments'),
]);
// 竞争执行
const fastest = await Promise.race([
fetch('/server1/data'),
fetch('/server2/data'),
]);
最佳实践
- 优先使用 async/await:代码更清晰易读
- 正确处理错误:使用 try/catch 或 .catch()
- 避免混合使用:不要混用回调和 Promise
- 注意性能:合理使用 Promise.all 进行并发优化