侧边栏壁纸
  • 累计撰写 47 篇文章
  • 累计创建 2 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

async/await的原理

async/await 是 基于 Promise 的语法糖,其目标是让异步代码的书写和阅读更像同步代码。

实现的关键:async/await 的底层可以看作 Generator 函数(生成器)和 Promise 的结合,并通过一个自动执行器(auto-runner) 来驱动。

  1. Generator 函数的暂停与恢复
    Generator 函数(通过 function*定义)可以通过 yield 关键字暂停执行,并通过 gen.next()方法恢复执行。这与 await 的等待行为非常相似,因此常被用来模拟 async/await。
  2. 实现自动执行器
    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);
    });
0

评论区