这个实现主要分为三部分:
- asyncFunc 函数返回一个 Promise,这里用 setTimeout 模拟异步操作
- asyncAwait 函数接收 asyncFunc,并返回一个新的函数。这个函数会启动一个生成器函数不断调用 next 方法
- 在 Promise 的 executor 中定义 next 方法。这个方法检查结果,如果是 Promise 则等待其 resolve,否则继续执行生成器中的下一步。这个过程一直循环直到生成器终止
- 最后返回一个 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的功能:
- async函数返回Promise
- asyncAwait函数封装async函数,返回一个新的Promise
- 在asyncAwait函数中,我们通过递归调用next方法来获取异步操作的结果
- 当next()的返回值不是thenable时结束递归,避免调用栈过大
- 异步操作完成后,将其结果作为Promise的resolve值返回
所以通过这个简单实现,我们可以在 asyncAwait 函数中 awaits 多个 Promise,而实际上启动了一个生成器不断执行异步任务,直到最终Resolve出一个结果。这也就是 async/await 的基本原理与实现方式