手写 async/await 原理浅析带注释

102 阅读2分钟

这个实现主要分为三部分:

  1. asyncFunc 函数返回一个 Promise,这里用 setTimeout 模拟异步操作
  2. asyncAwait 函数接收 asyncFunc,并返回一个新的函数。这个函数会启动一个生成器函数不断调用 next 方法
  3. 在 Promise 的 executor 中定义 next 方法。这个方法检查结果,如果是 Promise 则等待其 resolve,否则继续执行生成器中的下一步。这个过程一直循环直到生成器终止
  4. 最后返回一个 Promise,在生成器终止时 resolve,并将结果值resolve出去
// async函数返回一个Promise
function asyncFunc() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('async result codewhite');
        }, 1000);
    });
}

// 封装async函数,返回Promise
function asyncAwait(asyncFunc) {
    return function () {
        return new Promise((resolve, reject) => {
            // 定义变量保存异步操作结果
            let result;

            // 获取异步函数的迭代器
            const iterator = asyncFunc();

            // 如果是迭代器,获取其next方法
            let next;
            if (typeof iterator.next === 'function') {
                next = iterator.next;
            } else {
                next = () => {}; // 赋值空函数
            }

            function step() {
                // 递归调用next方法获取异步操作结果
                let res = next();
                // 判断res是否为thenable(Promise),不是则终止递归
                if (res && res.then) {
                    // 如果是Promise,等待其resolve后获取值
                    res.then((value) => {
                        result = value;
                        step();
                    });
                }
            }

            // 开始递归调用
            step();

            // 异步操作完成后,将最终结果作为Promise的resolve值
            resolve(result);
        });
    };
}

// 测试代码
asyncFunc().then((value) => {
    console.log(value); // undefined
});

const wrapped = asyncAwait(asyncFunc);
wrapped().then((value) => {
    console.log(value); // async result codewhite
});

上述代码中,我们手写实现了async/await的功能:

  1. async函数返回Promise
  2. asyncAwait函数封装async函数,返回一个新的Promise
  3. 在asyncAwait函数中,我们通过递归调用next方法来获取异步操作的结果
  4. 当next()的返回值不是thenable时结束递归,避免调用栈过大
  5. 异步操作完成后,将其结果作为Promise的resolve值返回

所以通过这个简单实现,我们可以在 asyncAwait 函数中 awaits 多个 Promise,而实际上启动了一个生成器不断执行异步任务,直到最终Resolve出一个结果。这也就是 async/await 的基本原理与实现方式