js中的生成器函数Generator中yeild用法+js中的生成器函数Generator浅封装一下

295 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

参考链接

****1. js中的生成器函数Generator

yield是什么

  • yield是ES6的新关键字,使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return关键字。
  • yield关键字实际返回一个IteratorResult(迭代器)对象,它有两个属性,value和done,分别代表返回值(yield表达式求值的结果)和是否完成。
  • yield无法单独工作,需要配合generator(生成器)的其他函数,如next,懒汉式操作,展现强大的主动控制特性。
  • next()方法里如果有参数,该参数 表示上一次yield的返回值

image.png

生成器说明

image.png

yeild可以在不同阶段从外部直接向内部注入不同的值来调整函数的行为

注:

image.png

  1. 函数名前面有个*号 表示 该函数是个生成器
  2. 首次调用next()方法表示开始执行generator函数
  3. 之后在执行时遇到yield表达式,就暂停执行yield表达式之后的操作,但是yield表达式要执行,并且将yield表达式之后的值作为返回对象的value值:
    比如:上面截图中的生成器(generator)函数,第一次调用next(),yield表达式x+1执行,但是2*(yield(x+1))并不会执行
  4. 再次调用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)
}

image.png

image.png

分析

分析

next() 传参是对yield整体的传参,否则yield类似于return

A组

  1. x恒为5,所以第一次调用传空没问题,可得到对应的第一个yield返回值:yield (x + 1)
  2. 第二次调用,无参数传入,所以y为NaN(2* undefined),自然得不到z
  3. 第三次调用同上分析

B组

  1. Generator函数调用和普通函数不一样,前者会返回一个迭代器

  2. 当第一次调用next时,传参会被忽略,并且函数暂停在yield(x+1)处,【所以返回5+1=6】

  3. 当第二次调用next时,传入的参数12会被当做上一个yield表达式的返回值,如果你不传参,yield将永远返回undefined。此时var y=212=24,【所以第二个yield等于212/3=8】

  4. 当第三次调用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}
    }
}

image.png

举例3-----------------------------------------------------------------------------

function* fn(){
    var a=yield 'hello';
    yield;
    console.log(a);
}

image.png

image.png

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)

运行结果

image.png