es6之Generator
Posted sunmarvell
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了es6之Generator相关的知识,希望对你有一定的参考价值。
Generator 函数是 ES6 提供的一种异步编程解决方案.
执行 Generator 函数会返回一个遍历器对象
Generator 函数是一个普通函数,但是有两个特征。一是,function
关键字与函数名之间有一个星号;二是,函数体内部使用yield
表达式,定义不同的内部状态(yield
在英语里的意思就是“产出”)
{ // genertaor基本定义 let tell=function* (){ yield ‘a‘; yield ‘b‘; return ‘c‘ }; let k=tell(); console.log(k.next()); console.log(k.next()); console.log(k.next()); console.log(k.next()); } //{value: "a", done: false} // {value: "b", done: false} // {value: "c", done: true} // {value: undefined, done: true}
调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象。
下一步,必须调用遍历器对象的next
方法,使得指针移向下一个状态。也就是说,每次调用next
方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield
表达式(或return
语句)为止。换言之,Generator 函数是分段执行的,yield
表达式是暂停执行的标记,而next
方法可以恢复执行。
与 Iterator 接口的关系
任意一个对象的Symbol.iterator
方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。
由于 Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator
属性,从而使得该对象具有 Iterator 接口。
{ let obj={}; obj[Symbol.iterator]=function* (){ yield 1; yield 2; yield 3; } for(let value of obj){ console.log(value); } } //1 //2 //3
next 方法的参数
yield
表达式本身没有返回值,或者说总是返回undefined
。next
方法可以带一个参数,该参数就会被当作上一个yield
表达式的返回值。
function* foo(x) { var y = 2 * (yield (x + 1)); var z = yield (y / 3); return (x + y + z); } var a = foo(5); a.next() // Object{value:6, done:false} a.next() // Object{value:NaN, done:false} a.next() // Object{value:NaN, done:true} var b = foo(5); b.next() // { value:6, done:false } b.next(12) // { value:8, done:false } b.next(13) // { value:42, done:true }
上面代码中,第二次运行next
方法的时候不带参数,导致 y 的值等于2 * undefined
(即NaN
),除以 3 以后还是NaN
,因此返回对象的value
属性也等于NaN
。第三次运行Next
方法的时候不带参数,所以z
等于undefined
,返回对象的value
属性等于5 + NaN + undefined
,即NaN
。
如果向next
方法提供参数,返回结果就完全不一样了。上面代码第一次调用b
的next
方法时,返回x+1
的值6
;第二次调用next
方法,将上一次yield
表达式的值设为12
,因此y
等于24
,返回y / 3
的值8
;第三次调用next
方法,将上一次yield
表达式的值设为13
,因此z
等于13
,这时x
等于5
,y
等于24
,所以return
语句的值等于42
。
注意,由于next
方法的参数表示上一个yield
表达式的返回值,所以在第一次使用next
方法时,传递参数是无效的。
在抽奖逻辑显示上的应用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script type="text/javascript"> { let draw=function(count){ //具体抽奖逻辑 console.info(`剩余${count}次`) } let residue=function* (count){ while (count>0) { count--; yield draw(count); } } let star=residue(5); let btn=document.createElement(‘button‘); btn.id=‘start‘; btn.textContent=‘抽奖‘; document.body.appendChild(btn); document.getElementById(‘start‘).addEventListener(‘click‘,function(){ star.next(); },false) } </script> </body> </html>
与Promise结合的应用
{ // 长轮询 let ajax=function* (){ yield new Promise(function(resolve,reject){ setTimeout(function () { resolve({code:0}) //resolve({code:1}) }, 200); }) } let pull=function(){ let generator=ajax(); let step=generator.next(); step.value.then(function(d){ if(d.code!=0){ setTimeout(function () { console.info(‘wait‘); pull() }, 1000); }else{ console.info(d); } }) } pull(); }
以上是关于es6之Generator的主要内容,如果未能解决你的问题,请参考以下文章