2026-10-31 15:28:59
JavaScript 本身是单线程语言,不支持传统多线程协程,但通过 Generator 函数和 Async/Await 实现了类似协程的“可暂停与恢复执行”能力,从而支持异步流程的有序控制。以下是具体实现方式及核心机制:
1. Generator:手动控制的协程Generator 是 ES6 引入的特殊函数,通过 function* 定义,使用 yield 暂停执行,外部通过迭代器对象控制恢复,实现协程的核心特征。
执行中断与上下文保留遇到 yield 时,函数暂停执行,保留当前变量状态(如局部变量、循环位置等),下次恢复时从暂停处继续。
外部控制与双向通信
返回迭代器对象,通过 .next() 手动恢复执行。
.next(value) 可向函数体内传值(作为 yield 表达式的返回值)。
yield 表达式可向外返回值(通过 .next().value 获取)。
示例
function* counter() { let count = 0; while (true) { yield ++count; // 暂停并返回值 }}const gen = counter();console.log(gen.next().value); // 1(恢复执行,count=1)console.log(gen.next().value); // 2(恢复执行,count=2)每次调用 .next() 恢复执行,直到下一个 yield 或函数结束。
类似“可随时暂停和恢复的任务”,具备协程的协作式调度特性。
早期应用Generator 最初用于解决回调地狱,配合工具库(如 co)实现自动执行异步流程,但需手动驱动或依赖外部库。
Async/Await 是 Generator 的语法升级,底层依赖 Promise,但以同步语法自动处理异步流程,无需手动驱动。
自动执行机制
async 函数自动返回 Promise,内部使用 await 暂停执行,直到 Promise 完成(resolve/reject)。
无需手动调用 .next(),引擎自动处理暂停与恢复。
错误处理与语义清晰
使用 try/catch 捕获异步错误,结构接近同步代码。
示例:async function fetchData() { try { const res = await fetch('/api/data'); // 暂停,等待响应 const data = await res.json(); // 暂停,等待解析 return data; } catch (err) { console.error(err); // 捕获异步错误 }}fetchData().then(data => console.log(data));
代码逻辑线性展开,避免回调嵌套或 Generator 的手动控制。
与 Generator 的关系Async/Await 可视为 Generator + Promise + 自动执行器 的语法糖。例如,以下 Generator 代码需手动驱动:
function* asyncTask() { const res = yield fetch('/api/data'); // 暂停,需外部处理 const data = yield res.json(); return data;}// 需配合 co 库或手动调用 .next()而 Async/Await 直接内置流程控制,成为现代异步编程标准。
Generator 的原始模型提供协程的基础能力(暂停/恢复、双向通信),但需手动控制或依赖工具库,适合底层实现。
Async/Await 的升级
自动化执行流程,简化异步代码。
结合 Promise 的状态管理(pending/fulfilled/rejected),提供更可靠的错误处理。
成为 ES2017 后的主流异步编程方式。