最近在學習redux-saga,因爲redux-saga須要使用Generator函數,因此下來就回顧了一下Generatorjavascript
Generator 函數是 ES6 提供的一種異步編程解決方案,語法行爲與傳統函數徹底不一樣java
寫法上Generator函數與普通函數沒什麼區別,只是在function
關鍵字後面多了一個*
號,函數內部多了一個yield
關鍵字編程
function* demo() { console.log(1) yield 111 console.log(2) yield 222 console.log(3) return 333 }
上面的函數即爲一個Generator函數,Generator調用後並不會直接執行,而是返回一個指向內部狀態的指針對象須要調用該指針對象的next
方法纔會向下執行,當遇到yield
關鍵字的時候,函數會掛起,交給外部,直到遇到下一次調用next
方法redux
let g = demo()
異步
此時若咱們第一次調用async
let val1 = g.next() // 打印 1,val1 = {value: 111, done: false} let val2 = g.next() // 打印 2,val2 = {value: 222, done: false} let val3 = g.next() // 打印 3,val3 = {value: 333, done: true}
根據結果咱們能夠很清楚的看到當返回值的done
爲true
的時候就表明Generator執行完畢,此外Generator函數還能夠被循環異步編程
for (let val of demo()) { console.log(val) } // val依次會打印出 1十一、222,注意當done爲true的時候不會打印value的值
固然Generator在工做中最經常使用到的就是處理異步函數,下面舉個例子:函數
function demo(a, b) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(a + b) }, 1000) }) } function* gen(val) { let a = yield demo(1, 2) console.log(a) let b = yield '123' return b }
這裏須要注意的是,變量a
的值是須要next
方法傳入的學習
let g = gen() let {value} = g.next()
此時函數中的變量a的值就是再次調用next
傳入的值, 好比g.next(value)
,則此時a的值就是一個Promise的實例,顯然這不是咱們想要的,咱們指望拿到的是Promise.resolve
的值指針
那麼根據上面的結果咱們能夠編寫一個Generator執行器
function execGen(gen) { let g = gen() function deep(val) { let {value, done} = g.next(val) if (done) { return } if (value instanceof Promise) { value.then(data => { deep(data) }) } else { deep(value) } } deep() } execGen(gen) // gen函數的console會正確的打印出值3
其實若是不是redux-saga的話我感受我工做中基本不會用到Generator函數,我的感受更優雅的是async/await 來處理異步狀況
async function handler() { try{ let val = await demo() }catch (e) { } }
最後仍是指望有大佬可以幫忙指出相比於async/await,Generator有什麼優點^_^