大家都知道async和await是语法糖,那么我们今天就来剖析一下不使用语法糖要怎么实现同样的功能
文章目录
- 一、生成器
- 二、实现async/await
一、生成器
async/await
的行为类似于 可暂停和恢复的函数,这正是生成器的特性,让我们首先来补一下生成器的知识:
通过function* 声明一个生成器函数。生成器函数可以退出,并在稍后重新进入,其上下文会在重新进入时保存。箭头函数不能定义生成器函数
通过yield 关键字用于暂停和恢复生成器函数
调用生成器函数会返回迭代器对象Generator
迭代器对象的
next()
方法被调用时,生成器函数的主体会被执行,直到遇到下一个yieldnext()方法返回一个对象,其
value
属性包含了yield
表达式的值,done
属性是布尔类型,表示生成器是否已经返回了最后一个值在生成器中执行
return
语句会使生成器结束
function* a() {yield 1;yield 2;return 3
}
b = a() // Generator对象
b.next() // {value: 1, done: false}
b.next() // {value: 2, done: false}
b.next() // {value: 3, done: true}
二、实现async/await
1.环境准备;准备一个异步函数和一个生成器函数,
function fn(nums) {return new Promise((resolve, reject) => {setTimeout(() => {resolve(nums * 2);}, 1000);});
}function* gen() {const num1 = yield fn(1);const num2 = yield fn(num1);const num3 = yield fn(num2);return num3;
}
准备一个async函数作为对照
async function asyncFn() {const num1 = await fn(1)const num2 = await fn(num1)const num3 = await fn(num2)return num3
}
asyncFn().then(res => console.log(res)) // 3秒后输出 8
2.编写一个函数,接收gen函数,返回具有async函数功能的函数
// 1.async函数始终返回Promise
function myAsync(gen){return ()=>{return new Promise((resolve,reject)=>{})}
}
3.实现具体细节
function myAsync(gen) {return () => {return new Promise((resolve, reject) => {const g = gen();const next1 = g.next();next1.value.then((res) => {const next2 = g.next(res);next2.value.then((res2) => {const next3 = g.next(res2);next3.value.then((res3) => {const next4 = g.next(res3);resolve(next4.value);});});});});};
}
const asyncGen = myAsync(gen);asyncGen().then((res) => console.log(res)); // 3秒后输出 8
到这里已经实现了基本功能,输出与asyncFn函数的输出一致,下一步我们改写函数,将固定的yield改为动态
4.修改代码
function myAsync(gen) {return () => {const g = gen(arguments);return new Promise((resolve, reject) => {// 递归执行function next(key, args) {// 异常处理let res;try {res = g[key](args);} catch (err) {return reject(err);}const { value, done } = res;if (done) {return resolve(value); // 递归退出条件} else {return Promise.resolve(value).then((res) => next("next", res),(err) => next("throw", err));}}next("next");});};
}