JavaScript 异步发展史:从地狱到天堂(回调 → Promise → async/await)

这是前端/Node.js 开发者必须掌握的历史脉络,看懂它,你就彻底明白为什么 async/await 是最终形态,也能彻底理解“一切都可能是异步”的设计根源。


时代 1:回调函数(Callback)—— 混沌时代(ES5 及以前)

核心特点

  • 异步完成后,通过函数调用通知结果
  • 所有异步逻辑都写在嵌套函数里
  • 简单,但嵌套一多就彻底失控

代码示例(回调地狱 Callback Hell)

假设你要依次做 3 件事:

  1. 获取用户信息
  2. 根据用户ID获取订单
  3. 根据订单ID获取商品详情
// 回调嵌套 = 回调地狱
getUser(function(err, user) {
  if (err) throw err;

  getOrder(user.id, function(err, order) {
    if (err) throw err;

    getGoods(order.id, function(err, goods) {
      if (err) throw err;

      console.log(goods);
      // 还能继续嵌套...
    });
  });
});

致命缺点

  1. 横向嵌套(金字塔代码),可读性极差
  2. 异常处理混乱(每个回调都要判断 err)
  3. 无法复用、无法取消、无法并行
  4. 代码难以维护,被称为回调地狱

时代 2:Promise —— 秩序时代(ES6 2015)

核心特点

  • 把异步操作封装成对象,解决嵌套问题
  • 用 .then() 链式调用,代码变平
  • 统一异常处理 .catch()
  • 支持并行 Promise.all

Promise 是中间层解决方案,不是语法糖,是语言原生类。

代码示例(链式调用)

// 扁平化,告别嵌套
getUser()
  .then(user => getOrder(user.id))
  .then(order => getGoods(order.id))
  .then(goods => console.log(goods))
  .catch(err => console.error('统一捕获异常', err));

优点

  1. 代码变平,不再横向嵌套
  2. 统一异常处理
  3. 支持并行/串行/竞赛等异步流程

缺点

  • 依然是函数式链式写法,和同步代码思维不同
  • 流程控制复杂(循环、条件判断在 then 里很别扭)
  • 代码还是不够像自然逻辑

时代 3:Generator + co —— 过渡时代(ES6 2015)

这是async/await 的前身,你只需要知道:

  • Generator 可以暂停函数
  • 配合 co 库可以自动执行异步
  • 写法已经接近同步,但需要库支持、语法繁琐
// 写法接近同步,但需要库,原生不支持自动执行
co(function* () {
  const user = yield getUser();
  const order = yield getOrder(user.id);
  const goods = yield getGoods(order.id);
  console.log(goods);
});

它证明了:用同步写法写异步是可行的,于是催生了最终形态。


时代 4:async/await —— 终极时代(ES2017)

核心特点

  • 语言原生支持,运行时级特性
  • 完全同步写法,执行异步逻辑
  • 基于 Promise,但写法更自然
  • 完美适配 JS “一切皆异步”的设计前提

代码示例(最终形态)

// 像读小说一样写异步
async function getDetail() {
  try {
    const user = await getUser();
    const order = await getOrder(user.id);
    const goods = await getGoods(order.id);
    console.log(goods);
  } catch (err) {
    console.error(err);
  }
}

为什么是终极形态?

  1. 符合人类思维:从上到下顺序执行
  2. 原生支持暂停/恢复(运行时能力)
  3. 同步/异步异常统一处理(try/catch)
  4. 兼容所有 Promise API
  5. 让 JS 真正做到:不用关心是否异步,写法完全一致

一张表看懂整个进化史

方案 写法 异常处理 可读性 地位
回调 嵌套金字塔 分散混乱 ⭐ 历史淘汰
Promise .then() 链式 统一 catch ⭐⭐⭐ 基础支撑
Generator yield + co 一般 ⭐⭐⭐⭐ 过渡方案
async/await 同步写法 try/catch ⭐⭐⭐⭐⭐ 最终标准

核心结论

  1. JS 天生单线程 → 必须异步 → 异步是默认模式
  2. 回调太烂 → Promise 解决嵌套 → 但不够自然
  3. async/await 是运行时原生特性,专门为 JS 异步模型设计
  4. 它的设计前提:我不管你是不是异步,我都按同步写法处理
    → 这就是 “一切都可能是异步的” 真正含义

总结

  • 回调:解决了异步,但制造了地狱
  • Promise:规范化异步,铺平代码
  • async/await:语言原生支持,用同步写法完美适配 JS 异步本质
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容