JavaScript異步之generator函數

接觸過Ajax請求的會遇到過異步調用的問題,爲了保證調用順序的正確性,一般我們會在回調函數中調用,也有用到一些新的解決方案如Promise相關的技術。

在異步編程中,還有一種常用的解決方案,它就是Generator生成器函數。顧名思義,它是一個生成器,它也是一個狀態機,內部擁有值及相關的狀態,生成器返回一個迭代器Iterator對象,我們可以通過這個迭代器,手動地遍歷相關的值、狀態,保證正確的執行順序。

generator基本用法

最簡單的generator函數,其實它就是一個普通的函數,但是它有兩個特徵:
1.就是function關鍵字與函數名之間有一個*號,
2.就是函數體內使用yield表達式來遍歷狀態:

function* generator(){
yield 'one'
yield 'two'
return 'three'
}
let Ljj = generator()
console.log(Ljj)
console.log(Ljj.next())  
console.log(Ljj.next())
console.log(Ljj.next())
console.log(Ljj.next())

輸出:
在這裏插入圖片描述
定義了一個generator的生成器函數,調用之後返回了一個迭代器對象Ljj

調用next方法後,函數內執行第一條yield語句,輸出當前的狀態done(生成器函數是否已經執行完畢並返回)以及返回值value(一般爲yield關鍵字後面的運算結果)

每調用一次next,則執行一次yield語句,並在該處暫停

當在生成器函數中顯式 return 時,會導致生成器立即變爲完成狀態,就退出了生成器函數,後續如果還有yield操作就不再執行了,即調用 next() 方法返回的對象的 done 爲 true。如果 return 後面跟了一個值,那麼這個值會作爲當前調用 next() 方法返回的 value 值。

yield和yield*

function* generator() {
      yield 'one'
      yield* generator2(13)
      return 'three'
}
function* generator2(num) {
      yield num
      yield num + 1
}
let Ljj = generator()
console.log(Ljj.next())
console.log(Ljj.next())
console.log(Ljj.next())
console.log(Ljj.next())

輸出:
在這裏插入圖片描述
從上面例子上我們可以看出:
當這個迭代器的 next() 方法被調用時,其內的語句會執行到第一個(後續)出現yield的位置爲止,yield 是你給什麼它提取什麼,但是 yield* 會繼續向下請求,將執行權移交給另一個生成器函數(generator2),當前生成器(generator)暫停執行,直到沒的提取爲止。
注意yieldyield* 只能在generator函數內部使用,一般的函數內使用會報錯

next()中的傳參

調用 next()方法時,如果傳入了參數,那麼這個參數會作爲上一條執行的 yield 語句的返回值,例如:

function* generator(){
    x = yield 1;
    y = yield x * 2;
    yield y * 3;
}

var Ljj = generator();
console.log(Ljj.next());
console.log(Ljj.next());
console.log(Ljj.next(2));
console.log(Ljj.next());

輸出:
在這裏插入圖片描述
第一次調用next之後返回值x爲1,但在第二次調用next的時候x其實是undefined的,因爲generator不會自動保存相應變量值,我們需要手動的指定,這時y值爲NaN,在第三次調用next的時候執行到yield 3 * y,通過傳參將上次yield返回值y設爲2,得到結果6

for…of循環代替next()

除了使用.next()方法遍歷迭代器對象外,通過ES6提供的新循環方式for…of也可遍歷,但與next不同的是,它會忽略return返回的值:

function* generator() {
    yield 1;
    yield 2;
    return 3;
}

var Ljj = generator();

for (let i of Ljj ) {
    console.log(i) // 1 2
}

更多參考 參考 MDN - Generator
明日我們開始講一下JavaScript異步之async

友情鏈接:點擊查看所有文章目錄

友情鏈接:點擊查看 JavaScript異步系列文章目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章