JavaScript 作为单线程语言,早期依靠回调函数处理网络请求、定时器等异步任务。随着业务变复杂,回调嵌套越来越深,代码可读性和错误处理都变得困难。后来语言层面逐步引入 Promise、Generator,直到 Async/Await 才让异步代码看起来像同步代码。

回调地狱阶段
最开始我们写异步只能传回调函数,多个异步依赖就会出现层层嵌套:
// 回调地狱示例
getUser(function(user) {
getOrder(user.id, function(order) {
getDetail(order.id, function(detail) {
console.log(detail);
}, function(err) {
console.error(err);
});
}, function(err) {
console.error(err);
});
});
这种写法的问题在于:错误要靠每层手动传递,逻辑分散,重构成本很高。
Promise 带来扁平化
Promise 把异步结果封装成对象,用 then 串联,避免嵌套:
// 使用 Promise 改写
getUser()
.then(function(user) { return getOrder(user.id); })
.then(function(order) { return getDetail(order.id); })
.then(function(detail) { console.log(detail); })
.catch(function(err) { console.error(err); });
Promise 解决了回调嵌套,但链式调用仍不够直观,中间状态较多。
Generator 协程尝试
Generator 能暂停执行,配合执行器可模拟同步写法:
function* load() {
var user = yield getUser();
var order = yield getOrder(user.id);
var detail = yield getDetail(order.id);
return detail;
}
// 需要外部 runner 驱动,此处省略
Generator 思路接近 Async/Await,但需额外运行库,不够原生。
Async/Await 成为主流
ES2017 的 Async/Await 基于 Promise,语法最简单:
// Async/Await 写法
async function load() {
try {
var user = await getUser();
var order = await getOrder(user.id);
var detail = await getDetail(order.id);
console.log(detail);
} catch (err) {
console.error(err);
}
}
它让异步代码像同步一样书写,错误处理用 try catch 即可,是目前最推荐的方案。
演进对比
| 方案 | 可读性 | 错误处理 |
|---|---|---|
| 回调 | 差 | 手动传递 |
| Promise | 中 | catch 统一 |
| Generator | 较好 | 依赖运行器 |
| Async/Await | 好 | try catch |
从回调地狱到 Async/Await,JavaScript 异步模型朝着更简洁、更易维护的方向持续演进。
JavaScript异步编程Async_Await修改时间:2026-07-30 11:03:18