js css html

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

2022-12-21  本文已影响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 可以等待异步函数执行完毕再继续执行后面的代码。

上一篇 下一篇

猜你喜欢

热点阅读