generator
generator 的中文是生成器,它可以返回多次,不像普通函数,只能使用一次 return 来返回,yield 与遍历器对象的 next 方法配合可以进行多次返回
function* gen(x){
const y=yield x+1
const z=yield y*2
return x+y+z
}
let g=gen(3)
g.next()
g.next(4)
g.next(5)
//
{value:12,done:true}
next 不仅会启动 yield,也可以传参,不过是向上一个 yield 传参,换句话说,第一次调用 next 无需传参,或者说传参无效,只是用来启动 generator
分析一下过程:
调用 gen 函数,得到遍历器对象,并且参数为 3,这时 x 的值为 3
第一次调用 next,没有传参,x 的值为 3,返回的结果为 {value:4,done:false}
第二次调用 next,传参为 5,x 的值不变,为第一个 yield 传参,所以 y 的值变为 4,即 z 的值为 8,所以结果为 {value:8,done:false}
第三次调用 next,为第二个 yield 传参 5,所以 z 的值为 5,此时,x 为 3,y 为 4,z 为 5,结果为 {value:12,done:true}
async
async 是 promise 的语法糖之一,一般配合 await 使用,用来等待 promise,一种简洁的写法
async function async1(){
return 2
}
等价于
function async1(){
return Promise.resolve(2)
}
那么如果在 async 函数中返回 promise 会怎样呢
async function async1(){
return new Promise((resolve,reject)=>{
resolve(2)
})
}
这样的话由返回的 promise 决定状态,也就是
function async1(){
return new Promise((resolve,reject)=>{
new Promise((resolve2,reject2)=>{
resolve2()
}).then(()=>{
resolve()
})
})
}
前置知识已经够用了,让我们用 generator 的原理来实现简单的 async
对照着例子来写会更好理解一些,先做好例子
function* genF(){
console.log(1)
const t=yield p1(1)
console.log(t)
console.log(3)
const t2=yield 4
console.log(t2)
return new Promise((resolve,reject)=>{
resolve(5)
})
}
简而言之,我们要做一个模仿 async/await 的函数,让其自动执行,而且也会产生阻塞代码的效果,generator 可以帮助我们
function async(genF,...initialValue){
return new Promise((resolve,reject)=>{
let gen=genF.apply(null,initialValue)
function step(value){
let result=gen.next(value)
if(result.done){
resolve(result.value)
return;
}
Promise.resolve(result.value).then(data=>{
step(data)
},e=>{
reject(e)
})
}
})
}
我们必须手动开启 step 函数,step 函数会不断地取 next 返回的对象的 value,如果是 promise 的话,等待其 resolve 并传值给下次 step 函数,如果为非 promise 的话,将该值封装为 fulfilled 的 promise
在 result.done 为真时,说明已经走到了函数的返回值,我们可以直接 resolve 结果,如果是 promise 的话,async 的返回值的状态依旧由 result.value 来决定
来测试一下
function async(genF,...initialValue){
return new Promise((resolve,reject)=>{
let gen=genF.apply(null,initialValue)
step()
function step(value){
let result=gen.next(value)
if(result.done){
resolve(result.value)
return;
}
Promise.resolve(result.value).then(data=>{
step(data)
},e=>{
reject(e)
})
}
})
}
const p1=(t)=>new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(t*1000)
},t*1000)
})
function* genF(){
console.log(1)
const t=yield p1(1)
console.log(t)
console.log(3)
const t2=yield 4
console.log(t2)
const t3=yield p1(2)
console.log(t3)
return new Promise((resolve,reject)=>{
resolve(5)
})
}
async(genF).then(data=>{
console.log('end',data)
})
核心就是 generator 的执行机制和 promise 的状态与值的传递,此次总结也让我更加了解 promise