前言:异步函数(async、await),在如今开发中广泛使用,今天我们通过使用生成器(Generator),模拟异步函数,看下异步函数究竟是如何实现的。
Generator函数的详解可以参考这篇文章:
js中Generator函数详解_js generator_月光晒了很凉快的博客-CSDN博客
实现步骤
1、创建Generator函数
// 模拟Promise请求
const promiseRequest = (res) => {
return new Promise((reslove,reject) => {
setTimeout(() => {
reslove(res)
},1000)
})
}
// 创建生成器
function* genFun(){
const res1 = yield promiseRequest('res')
console.log(res1);
}
2、执行函数
const gen = genFun()
gen.next().value.then(res1 => {
gen.next(res1)
})
执行函数后控制台打印res,这样我们就实现了这个异步请求,但是,当我们有多个异步请求时,又该如何实现呢,于是我们添加如下代码:
3、发送多个请求
// 模拟Promise请求
const promiseRequest = (res) => {
return new Promise((reslove,reject) => {
setTimeout(() => {
reslove(res)
},1000)
})
}
// 创建生成器
function* genFun(){
const res1 = yield promiseRequest('res')
const res2 = yield promiseRequest(res1 + ':张三')
const res3 = yield promiseRequest(res2 + '李四')
const res4 = yield promiseRequest(res3 + '王五')
console.log(res4) // 打印:'res:张三李四王五'
}
// 手动执行
const gen = genFun()
gen.next().value.then(res => {
gen.next(res).value.then(res1 => {
gen.next(res1).value.then(res2 => {
gen.next(res2).value.then(res3 => {
gen.next(res3)
})
})
})
})
通过不断的.then拿到结果,又将结果传递给next函数,再通过变量获取结果将结果传递给了下一次的请求,这样就实现了异步函数。但是这里的调用还需要自己每次手动编写,于是再一步优化!
4、自动执行
编写一个函数,传入生成器函数,使生成器函数自动执行,不需要每次手动
// 自动执行函数
function executeGen(fn){
const gen = fn();
(function exec(result){
const next = gen.next(result)
if(next.done) return next
next.value.then(res => exec(res))
})()
}
完整代码如下:
// 模拟Promise请求
const promiseRequest = (res) => {
return new Promise((reslove,reject) => {
setTimeout(() => {
reslove(res)
},1000)
})
}
// 创建生成器
function* genFun(){
const res1 = yield promiseRequest('res')
const res2 = yield promiseRequest(res1 + ':张三')
const res3 = yield promiseRequest(res2 + '李四')
const res4 = yield promiseRequest(res3 + '王五')
console.log(res4)
}
// 手动执行
// const gen = genFun()
// gen.next().value.then(res => {
// gen.next(res).value.then(res1 => {
// gen.next(res1).value.then(res2 => {
// gen.next(res2).value.then(res3 => {
// gen.next(res3)
// })
// })
// })
// })
// 自动执行2
function executeGen(fn){
const gen = fn();
(function exec(result){
const next = gen.next(result)
if(next.done) return next
next.value.then(res => exec(res))
})()
}
executeGen(genFun)