co.js是基於es6的generator實現的,至關於generator函數的一個自動執行器javascript
generator的簡單介紹java
function* fn(){ before() yield firstYield() yield secYield() end() } let gen = fn()//生成構造器 gen.next()//執行到第一個yield的位置,即只執行before(),firstYield() gen.next()//執行到第二個yield的位置,只執行secYield() gen.next()//執行直到結束,執行end()
co.js的實現es6
將一個異步函數thunk化異步
原函數函數
fs.readFile(path,callback)
thunk化後函數spa
let readFile = (path) => (callback) => fs.readFile(path, callback)
將readFile的異步執行generator函數傳入cocode
co(function* (){ let data1 = yield readFile('path1') console.log(data1)//顯示path1的文件的內容 let data2 = yield readFile('path2') console.log(data2)//顯示path2的文件內容 })
分析 co 函數blog
let co = (fn) => { let gen = fn()//將gen指向generator構造器 let next = (err, data) => { /**next函數,做用1.將上一步回調函數中data穿會給gen時期能爲其餘變量賦值,做用2:將gen向下一步運行,做用3.將next函數當成回調函數傳給gen的某一步,使其將data傳回next並執行下一步**/ let result = gen.next(data) if(! result.done){ result.value(next) } } next() }
分析執行過程ip
1.co(……)generator
執行let gen = fn (至關於gen =function* (){
let data1 = yield readFile('path1') console.log(data1)//顯示path1的文件的內容 let data2 = yield readFile('path2') console.log(data2)//顯示path2的文件內容 })
2.next()
執行let result = gen.next() (
至關於 let result = {done: false, value: readFile('path1')} (
至關於 let result = { done: false, value: (callback) => fs.readFile(‘path1’, callback)} ) ) 執行 if(! result.done ) //true||false 執行 result.value(next) ( 至關於 ((callback) => fs.readFile('path1',callback))(next) ( 至關於 fs.readFile('path1', next) ) )3. 當文件讀取完畢以後,調用 fs.readFile()執行回調函數next(err,data)返回第二步4.執行完畢,執行完generator函數的全部步驟