标签:rom done btn code end 不执行 恢复 count 关键字
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方法可以恢复执行。
任意一个对象的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
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(); }
标签:rom done btn code end 不执行 恢复 count 关键字
原文地址:https://www.cnblogs.com/sunmarvell/p/9149540.html