目录Generator是做什么的ES6如何停止遍历BasicSyntax-BasicSyntaxSeniorSyntax-AdvancedSyntaxnext添加参数returncontrolendthrowthrowexceptioncontrolGeneratorasynchronousScenarioCase彩票游戏的倍数使用Generator函数实现Iterator方法ES6-ES10学习布局Generator是做什么的?控制循环流程最重要的作用是解决异步编程中嵌套层次较深的问题。ES6如何让遍历“停止”ES5循环一旦执行,就无法停止functionloop(){for(leti=0;i<5;i++){console.log(i)}}loop()//0//1//2//3//5使用Generator,如何转换?//修改1,在循环前添加一个星号function*loop(){for(leti=0;i<5;i++){//修改2:添加yieldyieldconsole.log(i)}}//修改3:定义一个变量,将loop赋值给lconstl=loop()//此时没有输出,如果要输出,调用next方法l.next()//0l.next()//1l。next()//2l.next()//3l.next()//4l.next()//之后什么都不输出//应用场景:年会抽奖,自定义遍历器BasicSyntax——基本语法遍历器只是一个函数,但与普通函数不同的是,它在形式上多了一个*。yield可以在函数内部使用。当调用停止时,它不会立即执行,而是返回一个生成器对象。返回的生成器对象将调用next来控制循环。Generator函数的定义不能使用箭头函数,否则会报错SyntaxErrorfunction*gen(){letvalval=yield1console.log(val)}constl=gen()//"Generator{}"l.next()//无输出l.next()//undefinedyield表达式不返回值,因此undefinednext()的返回值第一个参数为返回值,第二个参数:done属性,表示是否遍历完成,false表示没有遍历完成,true表示遍历完成然后执行next()方法继续function*gen(){letvalval=yield[1,2,3]console.log(val)//undefined}constl=gen()console.log(l.next())//{value:Array(3),done:false}console.log(l.next())//{value:undefined,done:true}function*gen(){letval//yield后面跟着一个星号,然后是一个Traversable对象,所以你可以嵌套一个Generator对象val=yield*[1,2,3]console.log(val)//undefined}constl=gen()console.log(l.next())//{value:1,done:false}console.log(l.next())//{value:2,done:false}学到这里就明白了:yield有没有返回值?
没有,但是遍历器对象的next方法可以修改这个默认值。与ES5相比,它是如何控制程序的停止和启动的?
用yield控制停止,用next控制开始高级语法——高级语法如何控制函数外的函数内操作?next添加参数nextfunctionwrite参数,作为yield函数的返回值*gen(){letvalval=yield[1,2,3]console.log(val)//20}constl=gen()console.log(l.next(10))//{value:Array(3),done:false}//yield此时没有赋值,所以没有使用10console.log(l.next(20))//{value:undefined,done:true}//此时yield给val赋值,yield表达式的值为20。讲义中的例子可以更深入的理解。function*gen(){varval=100while(true){console.log(`before${val}`)val=yieldvalconsole.log(`return${val}`)}}letg=gen()console.log(g.next(20).value)//100之前//100console.log(g.next(30).value)//返回30//30之前//30console.log(g.next(40).value)//return40//before40//401.g.next(20)这段代码会执行gen的内部代码。当遇到第一个yieldpause时,console.log("before"+val)在100之前执行并输出,此时val为100,所以yieldval执行后返回100。请注意,yieldval不会分配给val。2.g.next(30)这行代码会继续执行gen里面的代码,也就是val=yieldval这一行,因为next传入的是30,所以yieldval的返回值为30,所以val是赋值30,执行到console.log("return"+val)输出30,此时没有遇到yield代码,继续执行,就是while的判断。继续执行console.log("before"+val)输出30之前,然后Executionencounteredanyieldvalprogramhalt。3.g.next(40)重复步骤2。returncontrolendfunction*gen(){letvalval=yield[1,2,3]console.log(val)//未执行}constl=gen()console.log(l.next(10))//{value:Array(3),done:false}console.log(l.return())//{value:undefined,done:true}//返回操作,函数终止console.log(l.next(20))//{value:undefined,done:true}添加返回值参数function*gen(){letvalval=yield[1,2,3]console.log(val)//未执行}constl=gen()console.log(l.next(10))//{value:Array(3),done:false}console.log(l.return(100))//{value:100,done:true}//返回运行,函数终止console.log(l.next(20))//{value:undefined,done:true}throw抛出异常控制函数*gen(){while(true){try{yield1}catch(e){console.log(e.message)//ss}}}constl=gen()console.log(l.next())//{value:1,done:false}console.log(l.next())//{value:1,done:false}console.log(l.next())//{value:1,done:false}l.throw(newError('ss'))//抛出错误,执行catchconsole.log(l.next())//{value:1,done:false}Generator异步解决方案之前说过最重要的作用是解决异步编程的深嵌套层次我们来看问题,即使没有大量嵌套代码的情况下使用Promise,回调函数仍然很多,可读性仍然不好。//Promisechainajax('/api/url1').then(value=>{returnajax('ajax/url2')}).then(value=>{returnajax('ajax/url3')}).then(value=>{returnajax('ajax/url4')}).catch(error=>{console.error(error)})要解决上面的问题,需要用到Generator函数。有一个更完整的库叫做co库。协函数库Explain可以看阮一峰的注释,不过后来有了async和await就很少用了。我们来看一个例子://定义一个生成器函数,ajax返回一个promise对象function*main(){try{constusers=yieldajax('/api/users.json')console.log(users)constposts=yieldajax('/api/posts.json')console.log(posts)consturls=yieldajax('/api/urls.json')console.log(urls)}catch(e){//捕获异常控制台.log(e)}}constg=main()//定义一个递归函数functionhandlerResult(result){if(result.done)return///如果为真,退出递归调用//result.valuereturnisapromise对象,使用then执行其结果result.value.then(data=>{//g.next(data)可以作为yield返回值,然后进入下一个递归handlerResult(g.next(data))//异常逻辑},error=>{g.throw(error)})}handleResult(g.next())caselotterydrawES5functiondraw(first=1,second=3,third=5){//candidates对于三个奖项,一个结果,一个随机数让firstPrize=['1A','1B','1C','1D','1E']让secondPrize=['2A','2B','2C','2D','2E','2F','2G','2H','2I','2J','2K','2L']让三等奖=['3A','3B','3C','3D','3E','3F','3G','3H','3I','3J','3K','3L','3M'、'3N'、'3O'、'3P'、'3Q'、'3R'、'3S'、'3T'、'3U'、'3V'、'3W'、'3X'、'3Y','3Z']letresult=[]letrandom//抽取一等奖for(leti=0;i
