一文搞懂async/await、generator、promise

361 阅读3分钟

一、核心关联

  1. 共同目标:解决 JavaScript 异步编程问题,避免回调地狱。

  2. 演进关系

    • Promise 是基础,提供链式调用管理异步操作。
    • Generator 通过暂停/恢复函数执行,为实现协程(Coroutine)提供可能。
    • async/await 基于 Promise 和 Generator 的语法糖,进一步简化异步代码。
  3. 底层依赖

    • async/await 的实现依赖 Promise 和 Generator 的机制。
    • Generator 可结合 Promise 实现类似 async/await 的效果(需手动控制执行)。

二、核心区别

特性PromiseGeneratorasync/await
语法特性.then() 链式调用function*yield 关键字async 函数和 await 关键字
执行控制自动执行,不可暂停可暂停和恢复(手动调用 next()自动执行,类似同步代码
错误处理.catch() 捕获链式错误需手动处理 try/catch支持 try/catch 同步式错误处理
返回值返回 Promise 对象返回迭代器(Iterator)返回 Promise 对象
适用场景单个或多个异步操作的链式管理复杂流程控制(如惰性计算、协程)简化异步代码,使其更接近同步逻辑
代码可读性链式调用易嵌套,复杂场景可读性下降需手动管理迭代器,代码较繁琐代码扁平化,可读性最高

三、代码示例对比

1. Promise(链式调用)

fetchData()
  .then(data => processData(data))
  .then(result => saveResult(result))
  .catch(err => console.error(err));

2. Generator(需手动控制执行)

function* asyncGenerator() {
  try {
    const data = yield fetchData();
    const result = yield processData(data);
    yield saveResult(result);
  } catch (err) {
    console.error(err);
  }
}

// 手动执行 Generator
const gen = asyncGenerator();
gen.next().value
  .then(data => gen.next(data).value)
  .then(result => gen.next(result));

3. async/await(自动执行)

async function asyncTask() {
  try {
    const data = await fetchData();
    const result = await processData(data);
    await saveResult(result);
  } catch (err) {
    console.error(err);
  }
}

四、关键区别详解

1. 执行机制

  • Promise:一旦创建便立即执行,无法暂停。
  • Generator:通过 yield 暂停执行,需外部调用 next() 恢复。
  • async/await:自动执行,await 会暂停当前 async 函数的执行,直到 Promise 完成。

2. 错误处理

  • Promise:依赖 .catch() 或链式中的第二个 then 参数。
  • Generator:需在函数内部用 try/catch 包裹 yield
  • async/await:直接使用 try/catch 捕获同步和异步错误。

3. 适用场景

  • Promise:适合简单异步任务链,如接口顺序调用。
  • Generator:适合需要精细控制执行流程的场景(如分批加载数据、状态机)。
  • async/await:适合复杂异步逻辑,尤其是多依赖的异步操作(如事务性操作)。

五、三者的协作关系

1. Generator + Promise = 类 async/await

通过工具库(如 co)可自动执行 Generator,模拟 async/await 的行为:

const co = require('co');
co(function* () {
  const data = yield fetchData();
  return yield processData(data);
});

2. async/await 本质是 Generator 的语法糖

Babel 等工具会将 async/await 转换为 Generator + Promise 的实现。

3. Promise 是三者共同的基础

无论使用 Generator 还是 async/await,最终仍需依赖 Promise 处理异步结果。


六、如何选择?

场景推荐方案理由
简单异步链式调用Promise代码简洁,无需复杂语法
需要精细控制函数执行流程Generator手动暂停/恢复,适合协程或惰性计算
复杂异步逻辑,追求代码可读性async/await同步式写法,易于维护
兼容旧环境(不支持 ES2017+)Promise + Generator通过 Polyfill 或工具库(如 co)实现

七、总结

  • Promise:异步编程的基石,适合链式调用。
  • Generator:提供函数暂停能力,适合复杂流程控制,但需手动管理。
  • async/await:基于前两者的语法糖,简化异步代码,提升可读性。

演进关系
Callback → Promise → Generator → async/await

选择建议

  • 现代项目中优先使用 async/await,必要时结合 Promise.all 等高级方法。
  • 在需要底层控制或兼容旧环境时,可回归 PromiseGenerator