美文网首页js css html
第十八节: TypeScript生成器(Generator)

第十八节: TypeScript生成器(Generator)

作者: 时光如剑 | 来源:发表于2022-12-21 22:12 被阅读0次

    生成器(Generator)

    迭代器和生成器是两个概念. 但这两个概念很容易混淆, 原因在于生成器会借助迭代器功能.

    生成器是一种能够中途停止,然后从停止的地方继续运行的函数。可以借助 yieldreturn 停止函数运行。

    通过function *来创建一个生成器函数, 在调用生成器函数后并不会立即执行函数中的代码,而是会返回一个迭代器对象通过调用迭代器对象的 next() 方法,可以获得 yield/return 的返回值。

    1. 生成器函数的特殊性

    一个正常的函数,如果没有 return 或者 throw 一个异常,一旦被调用在函数运行结束之前是不会停止的。

    如果再次调用这个函数,它会重新从第一行开始执行。

    例如:

    // 普通函数
    function fn(){
      console.log('hello')
      console.log('world')
      console.log(20)
      console.log(false)
    }
    

    相反,生成器函数可以中途停止, 然后从停止的地方继续执行

    生成器函数返回一个对象, 这个对象就是迭代器, 调用迭代器上的next()方法执行后续代码

    例如:

    // 生成器函数
    function * generatorFn(){
      console.log('开始执行')
    
      yield 'hello';
    
      console.log('暂停后再次执行')
      yield 'world';
    
      console.log('函数执行完毕')
    }
    
    // 执行生成器函数,获取迭代器
    let interator = generatorFn()
    
    // 调用next 方法获取值
    // 迭代器next() 方法返回 {value:,done:}
    // 如果要获取值,就调用value 方法
    let val = interator.next().value
    console.log('val', val)
    /*
      控制台打印结果:
        开始执行
        val hello
    */ 
    

    示例中,通过function *语法创建了一个生成器函数调用这个函数并赋值给变量 iterator,我们已经知道这是个迭代器对象。

    调用iterator对象上的 next() 方法,首先打印出 开始执行,然后遇到了 yield Hello,yield 会将后面的值返回,迭代器生成一个对象 { value: 'Hello, ', done: false },函数停止运行,直到再次调用 next() 方法。

    // 再次调用next 方法
    let val2 =  interator.next().value
    console.log('val2', val2)
    /*
      控制台打印结果:
        暂停后再次执行
        val2 world
    */
    

    再次调用 next() 方法,函数内继续执行,打印出 暂停后再次执行,遇到 yield 'World!',生成对象 { value: 'World!', done: false },函数停止运行,直到再次调用 next() 方法。

    // 再次调用next 方法
    let val3 =  interator.next().value
    console.log('val3', val3)
    /*
      控制台打印结果:
        函数执行完毕
        val3 undefined
    */
    

    2. 通过next()参数向生成器传值

    在调用 next() 的时候可以传递一个参数,在上次 yield 前接收到这个参数:

    例如:

    function* gen() { 
      console.log('开始执行')
      let res1 = yield 1
      console.log('中断后继续执行')
      console.log('res1',res1)
      
      let res2 = yield 2
      console.log('res2', res2)
      
      console.log('执行结束')
      return 3
    }
    
    let iterator = gen()
    console.log(iterator.next('first'))
    console.log(iterator.next('second'))
    console.log(iterator.next('third'))
    
    /*
      执行结果
        开始执行
        { value: 1, done: false }
        中断后继续执行
        res1 second
        { value: 2, done: false }
        res2 third
        执行结束
        { value: 3, done: true }
    
    */
    

    这里注意下,生成器最初没有产生任何结果,在第一次调用 next() 时传参是无意义的

    3. 小结:

    生成器还有另一个巨大的好处,就是把异步回调代码变成“同步”代码。

    async await 就是基于生成器函数的语法糖,await 可以等待异步函数执行完毕再继续执行后面的代码。

    相关文章

      网友评论

        本文标题:第十八节: TypeScript生成器(Generator)

        本文链接:https://www.haomeiwen.com/subject/ilepyrtx.html