持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
参考链接
yield是什么
- yield是ES6的新关键字,使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return关键字。
- yield关键字实际返回一个IteratorResult(迭代器)对象,它有两个属性,value和done,分别代表返回值(
yield表达式求值的结果)和是否完成。 - yield无法单独工作,需要配合generator(生成器)的其他函数,如next,懒汉式操作,展现强大的主动控制特性。
- next()方法里如果有参数,该参数 表示上一次yield的返回值
生成器说明
yeild可以在不同阶段从外部直接向内部注入不同的值来调整函数的行为
注:
- 函数名前面有个*号 表示 该函数是个生成器
- 首次调用next()方法表示开始执行generator函数
- 之后在执行时遇到yield表达式,就暂停执行yield表达式之后的操作,但是yield表达式要执行,并且将yield表达式之后的值作为返回对象的value值:
比如:上面截图中的生成器(generator)函数,第一次调用next(),yield表达式x+1执行,但是2*(yield(x+1))并不会执行 - 再次调用next(val)方法,继续向下执行,同时val参数可作为上个yield返回对象的value值,继续向下执行,如果没有传则默认为NaN。如此往复,知道执行完毕(done==true).
举例1-----------------------------------------------------------------------------
function* test(x){
var y=2*(yield(x+1))
var z=yield(y/3)
console.log('x='+x+',y='+y+',z='+z)
// a: x=5,y=NaN,z=undefined
// b: x=5,y=24,z=13
return (x+y+z)
}
分析
分析
next() 传参是对yield整体的传参,否则yield类似于return
A组
- x恒为5,所以第一次调用传空没问题,可得到对应的第一个yield返回值:yield (x + 1)
- 第二次调用,无参数传入,所以y为NaN(2* undefined),自然得不到z
- 第三次调用同上分析
B组
-
Generator函数调用和普通函数不一样,前者会返回一个迭代器
-
当第一次调用next时,传参会被忽略,并且函数暂停在yield(x+1)处,【所以返回5+1=6】
-
当第二次调用next时,传入的参数12会被当做上一个yield表达式的返回值,如果你不传参,yield将永远返回undefined。此时var y=212=24,【所以第二个yield等于212/3=8】
-
当第三次调用next时,传入的参数13会被当作上一个yield表达式的返回值,所以x=5,y=24,13,相加等于24
举例2-----------------------------------------------------------------------------
function* countAppleSales(){
for(var i=0;true;i++){
var reset = yield i;
if(reset){i=-1}
}
}
举例3-----------------------------------------------------------------------------
function* fn(){
var a=yield 'hello';
yield;
console.log(a);
}
js中的生成器函数Generator封装
function ajax(duration){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(duration+'ms 延时打印输出!, 当前位于'+new Date().getSeconds()+'秒')
resolve(duration)
},duration)
})
}
// 生成器函数
function* main(){
const user=yield ajax(2000)
console.log('user',user)
const posts=yield ajax(10000)
console.log(posts)
}
// 封装执行生成器函数
function fengzhuangFun(generator){
const g=generator()
function handleResult(result){
if(result.done) return // 生成器函数结束
result.value.then(data=>{
console.log('继续执行',data)
handleResult(g.next(data))
},error=>{
g.throw(error)
})
}
handleResult(g.next())
}
fengzhuangFun(main)
运行结果