es6-generator


    // yield只能配合Generator函数使用

    // function* helloGeneratot(){
    //   console.log("This is generator")
    // }
    
    // 这个时候如期的打印了日志,我们分析下,对于Generator函数,下面的语句
    // var h = helloGeneratot()
    // h.next()

    function* helloGeneratot(){
      yield "hello";
      yield "generator";
      return;
    }
    var h = helloGeneratot();
    console.log(h.next())
    console.log(h.next())
    console.log(h.next())
    console.log('-------------------------')

    // 二、Generator 函数与迭代器(Iterator)
    // 经过上一篇我们学过迭代器,大家对于迭代器接口的next方法应该不陌生,Generator函数也涉及到next()方法的调用,
    // 他们之间有什么关系呢?实现了迭代器接口的对象都可以for-of实现遍历。我们来测试下:
    function* helloGeneratot2(){
      yield "hello";
      yield "generator";
      return;
    }
    var h = helloGeneratot2()
    for(var value of h){
      console.log(value)
    }
    console.log('-------------------------')

    // helloGenerarot对象是支持for-of循环的,也说明Generator函数在原型上实现了迭代器接口,
    // 上面调用的next()方法其实就是迭代器的next()方法。我们继续来看next()方法。
    function* gen(x,y){
      let z = yield x+y;
      let result = z*x
      return result
    }
    var gen = gen(5,7)
    console.log(gen.next())
    console.log(gen.next())
    console.log('-------------------------')

    // 分析上面的代码:
    // 1、第一执行next(),运行"yield x+y",并返回x+y的运算结果11;
    // 2、第二次执行next(),运行"yield z*x",此时是z为11,x为5,运算结果为55才对,为何是NaN呢?第一次运行到yield x+y,就将结果返回,实际没有执行z的赋值;第二次运行时,执行的是let z=undefined,所以运算z*x的结果是NaN。

    // 那有没有办法解决这个问题,我们来改下这个例子:
    function* gen1(x,y){
      let z = yield x+y;
      let result = z*x
      return result
    }
    var g = gen1(5,6)
    var i = g.next()
    console.log(g.next(i.value))
    console.log('-------------------------')

    // 在实际工程中,我们可以用下面这种简单的方式
    function* gen3(x,y){
      let z,result;
      yield z = x+y;
      yield result = z*x;
      return result
    }
    var gen3 = gen3(4,5)
    console.log(gen3.next())
    console.log(gen3.next())

    // 执行return()方法后就返回done:true,Generator 函数遍历终止,后面的yield 3不会再执行了。
    // 与next()方法一样,return()也可以带参数。
    function* gen4(){
      yield 2;
      yield 3;
      yield 4;
    }
    var gen4 = gen4()
    console.log(gen4.next())
    console.log(gen4.next())
    console.log(gen4.return(5))
    console.log(gen4.next())
    console.log('-------------------------')

    // Generator函数中还有一种yield*这个表达方式,看看它有什么作用。
    function* foo(){
      yield 'a';
      yield 'b';
    }
    function* gen5(){
      yield 1;
      yield 2;
      yield* foo();
      yield 3;
    }
    var gen5 = gen5()
    console.log(g.next());//{value: 1, done: false}
   console.log(g.next());//{value: 2, done: false}
   console.log(g.next());//{value: "a", done: true}
   console.log(g.next());//{value: "b", done: true}
   console.log(g.next());//{value: "3", done: true}
   console.log('-------------------------')

    // 注意:yield* 后面只能适配Generator函数。

    //     四、应用

    //    讲了这么多,那么Generator函数用在什么场景呢?要回答这个问题,首先我们总结Generator它的特点,
    // 一句话:可以随心所欲的交出和恢复函数的执行权,yield交出执行权,next()恢复执行权。我们举几个应用场景的实例。
    //   1、协程
    //    协程可以理解成多线程间的协作,比如说A,B两个线程根据实际逻辑控制共同完成某个任务,A运行一段时间后,
    // 暂缓执行,交由B运行,B运行一段时间后,再交回A运行,直到运行任务完成。对于JavaScript单线程来说,
    // 我们可以理解为函数间的协作,由多个函数间相互配合完成某个任务。
    //   下面我们利用饭店肚包鸡的制作过程来说明,熊大去饭店吃饭,点了只肚包鸡,然后就美滋滋的玩着游戏等着吃鸡。
    // 这时后厨就开始忙活了,后厨只有一名大厨,还有若干伙计,由于大厨很忙,无法兼顾整个制作过程,需要伙计协助,
    // 于是根据肚包鸡的制作过程做了如下的分工。

    //   肚包鸡的过程:准备工作(宰鸡,洗鸡,刀工等)->炒鸡->炖鸡->上料->上桌
    //   大厨很忙,负责核心的工序:炒鸡,上料
    //   伙计负责没有技术含量,只有工作量的打杂工序:准备工作,炖鸡,上桌

   //大厨
   function* chef(){
     console.log("炒鸡") //炒鸡
     yield "worker";
     console.log("上料") //上料
     yield "worker";
   }

  //  伙计的活
  function* worker(){
    console.log("准备工作")
    yield "chef"
    console.log("炖鸡")
    yield "chef"
    console.log("上菜")
  }
  // 流程控制
  var ch = chef()
  var wo = worker()
  function run(gen){
    var v = gen.next()
    if(v.value === "chef"){
      run(ch)
    }else if(v.value === "worker"){
      run(wo)
    }
  }


  run(wo)

    //准备工作
    //炒鸡
    //炖鸡
    //上料
    //上菜


  // 2、异步编程

来源:ES6系列教程第三篇--Generator 详解

你可能感兴趣的:(es6)