亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

TypeScript 生成器(Generator)

迭代器和生成器這兩個概念總是很容易混淆,經過上節的學習我們知道迭代器是一個對象,那么本節首先要記?。?strong>生成器是一種能夠中途停止,然后從停止的地方繼續運行的函數。可以借助 yieldreturn 停止函數運行。

1. 慕課解釋

通過 function* 來創建一個生成器函數,在調用一個生成器函數后,并不會立即執行函數中的代碼,而是會返回一個迭代器對象,通過調用迭代器對象的 next() 方法,可以獲得 yield/return 的返回值。

2. 生成器函數的特殊性

一個正常的函數,如果沒有 return 或者 throw 一個異常,一旦被調用在運行結束之前是不會停止的。如果再次調用這個函數,它會再次從第一行開始執行。

function normalFunc() {
  console.log('I')
  console.log('cannot')
  console.log('be')
  console.log('stopped.')
}

In contrast, a generator is a function that can stop midway and then continue from where it stopped.

相反,生成器函數可以中途停止,然后從停止的地方繼續執行的。

生成器函數會返回一個對象,可以調用這個對象上的 next() 方法。

3. 示例代碼

function* generatorFunction() { 
  console.log('開始執行')
  yield 'Hello, '

  console.log('暫停后再次執行')
  yield 'World!'
}

let iterator = generatorFunction()

此時,通過 function* 語法創建了一個生成器函數,調用這個函數并賦值給變量 iterator,我們已經知道這是個對象。

console.log(iterator.next().value)
// 開始執行
// Hello, 

調用 iterator 對象上的 next() 方法,首先打印出 開始執行,然后遇到了 yield Hello,,yield 會將后面的值返回,生成器生成一個對象 { value: 'Hello, ', done: false },函數停止運行,直到再次調用 next() 方法。

console.log(iterator.next().value)
// 暫停后再次執行
// World!

再次調用 next() 方法,函數內繼續執行,打印出 暫停后再次執行,遇到 yield 'World!',生成對象 { value: 'World!', done: false },函數停止運行,直到再次調用 next() 方法。

console.log(iterator.next())

再次調用 next() 方法,這次函數內沒有返回值,也就是默認返回 undefined, 生成對象 { value: 'undefined', done: true }

4. 通過 next() 參數向生成器傳值

在調用 next() 的時候可以傳遞一個參數,在上次 yield 前接收到這個參數:

function* gen() { 
  console.log('開始執行')
  let res1 = yield 1
  console.log('中斷后繼續執行')
  console.log(res1)
  
  let res2 = yield 2
  console.log(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 }
中斷后繼續執行
second
{ value: 2, done: false }
third
執行結束
{ value: 3, done: true }

這里注意下,生成器最初沒有產生任何結果,在第一次調用 next() 時傳參是無意義的。

5. 小結

生成器還有另一個巨大的好處,就是把異步回調代碼變成“同步”代碼。async await 就是基于生成器函數的語法糖,await 可以等待異步函數執行完畢再繼續執行后面的代碼。