迭代函式 Generator函式的理解

2022-09-21 16:09:11 字數 4844 閱讀 1950

一、基本用法

generator函式跟普通函式在寫法上的區別就是,多了乙個星號*,並且只有在generator函式中才能使用yield

什麼是yield呢,他相當於generator函式執行的中途暫停點,比如下方有3個暫停點。而怎麼才能暫停後繼續走呢?那就得使用到next方法next方法執行後會返回乙個物件,物件中有value 和 done兩個屬性

function* gen() 

const g = gen()

console.log(g.next()) //

console.log(g.next()) //

console.log(g.next()) //

console.log(g.next()) //

可以看到最後乙個是undefined,這取決於你generator函式有無返回值

function* gen() 

const g = gen()

console.log(g.next()) //

console.log(g.next()) //

console.log(g.next()) //

console.log(g.next()) //

二、yield後面接函式

yield後面接函式的話,到了對應暫停點yield,會馬上執行此函式,並且該函式的執行返回值,會被當做此暫停點物件的value

function fn(num) 

function* gen()

const g = gen()

console.log(g.next())

// 1

// console.log(g.next())

// 2

//

console.log(g.next())

//

三、yield後面接peomise

前面說了,函式執行返回值會當做暫停點物件的value值,那麼下面例子就可以理解了,前兩個的value都是pending狀態的promise物件

function fn(num) , 1000)

})}function* gen()

const g = gen()

console.log(g.next()) // , done: false }

console.log(g.next()) // , done: false }

console.log(g.next()) //

但是其實我們想要的結果是兩個promise的結果1 和 2,那怎麼做呢?直接使用promise的then方法就行了

const g = gen()

const next1 = g.next()

next1.value.then(res1 => , done: false }

console.log(res1) // 1秒後輸出 1

const next2 = g.next()

next2.value.then(res2 => , done: false }

console.log(res2) // 2秒後輸出 2

console.log(g.next()) // 2秒後輸出

})})

四、next函式傳參

generator函式可以用next方法來傳參,並且可以通過yield來接收這個引數,注意兩點:

第一次傳參引數無效,只有從第二次開始next傳參才有用

next傳值時,要記住順序是,先右邊yield,後左邊接收引數

function* gen() 

const g = gen()

console.log(g.next()) //

console.log(g.next(11111))

// 11111

//

console.log(g.next(22222))

// 22222

//

五、promise+next傳參

看下這兩個組合起來會是什麼樣?

function fn(nums) , 1000)

})}function* gen()

const g = gen()

const next1 = g.next()

next1.value.then(res1 => , done: false }

console.log(res1) // 1秒後同時輸出 2

const next2 = g.next(res1) // 傳入上次的res1

next2.value.then(res2 => , done: false }

console.log(res2) // 2秒後同時輸出 4

const next3 = g.next(res2) // 傳入上次的res2

next3.value.then(res3 => , done: false }

console.log(res3) // 3秒後同時輸出 8

// 傳入上次的res3

console.log(g.next(res3)) // 3秒後同時輸出

})})

})

六、用generator函式實現async/await

其實上方的generator函式promise+next傳參,就很像async/await了,區別在於

gen函式執行返回值不是promise,asyncfn執行返回值是promise

gen函式需要執行相應的操作,才能等同於asyncfn的排隊效果

gen函式執行的操作是不完善的,因為並不確定有幾個yield,不確定會巢狀幾次

之前我們說到,async函式的執行返回值是乙個promise,那我們要怎麼實現相同的結果呢 

function* gen() 

function generatortoasync (generatorfn) )

}}const asyncfn = generatortoasync(gen)

console.log(asyncfn()) // promise

把之前的處理**,加入generatortoasync函式

function fn(nums) , 1000)

})}function* gen()

function generatortoasync(generatorfn) )

})})

})}}

const asyncfn = generatortoasync(gen)

asyncfn().then(res => console.log(res)) // 3秒後輸出 8

可以發現,其實已經實現了以下的async/await的結果了

async function asyncfn() 

asyncfn().then(res => console.log(res)) // 3秒後輸出 8

完善一下**上面的**其實都是死**,因為乙個async函式中可能有2個await,3個await,5個await ,其實await的個數是不確定的。同樣模擬,generator函式中,也可能有2個yield,3個yield,5個yield,所以把**寫成活的才行

function generatortoasync(generatorfn)  catch (error) 

// 解構獲得value和done

const = res

if (done) else

}go("next") // 第一次執行

})}}

const asyncfn = generatortoasync(gen)

asyncfn().then(res => console.log(res))

這樣的話,無論是多少個yield都會排隊執行了

示例:

async/await版本

async function asyncfn() 

const asyncres = asyncfn()

console.log(asyncres) // promise

asyncres.then(res => console.log(res)) // 8

使用generatortoasync函式的版本

function* gen() 

const gentoasync = generatortoasync(gen)

const asyncres = gentoasync()

console.log(asyncres) // promise

asyncres.then(res => console.log(res)) // 8

因此可以看出async/await是一種語法糖

Generator函式和可迭代物件相關概念

1.呼叫乙個生成器函式,並不會馬上執行它裡面的語句,而是返回這個生成器的迭代器 iterator 物件。2.呼叫迭代器的next 方法,會執行到第乙個出現yield的位置,返回yield後面的值,然後暫停。如果遇到yield 則執行權移交給另外乙個生成器函式 當前的暫停 3.next 方法的返回值為...

Generator函式與async函式的區別介紹

generator函式 generator函式是es2015提供的非同步解決方案,與普通函式有很大的不同 特徵 1 在function關鍵字後面跟乙個 號 2 在函式體內部使用yield表示式作為乙個狀態 generator函式返回乙個遍歷器,可通過for of方法遍歷每個狀態 用法 執行gener...

Generator函式學習

例子1 const test function x const a test 1 console.log a.next 3 x 2 3 console.log a.next 11 22 3 2 11 3 console.log a.next 2 18 3 2 3 console.log a.next...