async/await 是 基于 Promise 的语法糖,其目标是让异步代码的书写和阅读更像同步代码。
实现的关键:async/await 的底层可以看作 Generator 函数(生成器)和 Promise 的结合,并通过一个自动执行器(auto-runner) 来驱动。
- Generator 函数的暂停与恢复
Generator 函数(通过 function*定义)可以通过 yield 关键字暂停执行,并通过 gen.next()方法恢复执行。这与 await 的等待行为非常相似,因此常被用来模拟 async/await。 - 实现自动执行器
Generator 本身不会自动执行 yield 后的异步操作。我们需要一个自动执行器函数,它接收一个 Generator 函数作为参数,并返回一个 Promise。这个执行器的核心职责是:
启动 Generator 迭代器。
在遇到每个 yield 时,将其后的值(假设是一个 Promise)用 Promise.resolve()包装以确保一致性。
等待这个 Promise 完成,然后将结果通过 gen.next(result)传回 Generator 函数,并继续执行下一段代码。
处理错误和完成状态。
async function mockAsync() {
const result1 = await task1();
const result2 = await task2(result1);
return result2;
}
//Generator函数
function* mockAsyncGenerator() {
const result1 = yield task1(); // 暂停,等待 task1 完成
const result2 = yield task2(result1); // 暂停,等待 task2 完成
return result2;
}
//自动执行函数
function spawn(genFn) {
// 返回一个 Promise,模拟 async 函数的返回值
return new Promise((resolve, reject) => {
const gen = genFn(); // 创建迭代器对象
// 定义 step 函数,用于处理下一次迭代
function step(nextFn, arg) {
let nextResult;
try {
// 执行 next() 或 throw(),恢复 Generator 执行
nextResult = nextFn.call(gen, arg);
} catch (error) {
// 捕获同步错误,直接拒绝返回的 Promise
return reject(error);
}
const { value, done } = nextResult;
// 检查 Generator 是否执行完毕
if (done) {
// 完毕,用最终值 resolve 返回的 Promise
return resolve(value);
} else {
// 未完毕,保证 value 是一个 Promise,并等待其完成
return Promise.resolve(value).then(
// Promise 成功,将结果传入下一步,继续执行
(resolvedValue) => step(() => gen.next(resolvedValue)),
// Promise 失败,将错误抛入 Generator
(error) => step(() => gen.throw(error))
);
}
}
// 启动执行链
step(() => gen.next(undefined));
});
}
// 使用 spawn 执行 Generator 函数
spawn(mockAsyncGenerator)
.then(finalResult => {
console.log('Final result:', finalResult);
// 输出: Final result: Result from task1 -> Result from task2
})
.catch(error => {
console.error('Caught an error:', error);
});
评论区