您说得对!Generator 的 yield 配合执行器确实可以模拟 await 的效果。让我用一个更直观的例子展示这种对应关系。
Generator 模拟 async/await
// 模拟异步函数
function delay(ms, value) {return new Promise(resolve => setTimeout(() => resolve(value), ms));
}// Generator函数(类似async函数)
function* asyncTask() {console.log('开始任务');const result1 = yield delay(1000, '第一步完成');console.log(result1);const result2 = yield delay(1500, '第二步完成');console.log(result2);return '任务完成';
}// 执行器(类似await的底层实现)
function runGenerator(genFn) {const iterator = genFn();function handle(result) {if (result.done) return Promise.resolve(result.value);return Promise.resolve(result.value).then(res => handle(iterator.next(res))).catch(err => iterator.throw(err));}return handle(iterator.next());
}// 执行Generator
runGenerator(asyncTask).then(finalResult => {console.log('最终结果:', finalResult);
});
与async/await的对应关系
| Generator写法 | async/await写法 | 说明 |
|---|---|---|
function* |
async function |
声明异步函数 |
yield |
await |
暂停执行等待Promise |
runGenerator |
JavaScript引擎内置 | 自动执行器 |
转换为async/await版本
// 同样的异步函数
function delay(ms, value) {return new Promise(resolve => setTimeout(() => resolve(value), ms));
}// async/await版本
async function asyncTask() {console.log('开始任务');const result1 = await delay(1000, '第一步完成');console.log(result1);const result2 = await delay(1500, '第二步完成');console.log(result2);return '任务完成';
}// 直接调用
asyncTask().then(finalResult => {console.log('最终结果:', finalResult);
});
关键区别
-
语法糖:
- async/await是Generator+P执行器的语法糖
- 不需要手动写执行器
-
错误处理:
// Generator版本 function* task() {try {const res = yield asyncOp();} catch(err) {// 处理错误} }// async/await版本 async function task() {try {const res = await asyncOp();} catch(err) {// 处理错误} } -
返回值:
- Generator函数返回迭代器
- async函数返回Promise
历史发展
- 回调地狱 → 2. Promise → 3. Generator → 4. async/await
Generator是JavaScript异步编程演进过程中的重要一步,它让开发者可以用同步的方式写异步代码,最终演变成了更简洁的async/await语法。