一、基本用法
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...