es6 generator函數,咱們都知道asycn和await是generator函數的語法糖,那麼genertaor怎麼樣才能實現asycn和await的功能呢?es6
1.thunk函數 將函數替換成一個只接受回調函數做爲參數的單參數函數編程
/* Thunk 函數替換的不是表達式,而是多參數函數,將其替換成一個只接受回調函數做爲參數的單參數函數。 */ /* 注 fn 傳入的是一個函數,傳入一個函數造成的方法,傳入參數,最後傳入callback 在通過兩次函數調用後,該函數就換成一個只接受回調函數做爲參數的單參數函數 */ var thunk = function(fn) { return function() { let args = Array.prototype.slice.call(arguments); return function (callback) { args.push(callback); return fn.apply(this,args) } } }
2.generator異步編程的示例promise
/* 異步執行方法 */ function timeout(ms,val) { return new Promise((res)=>{ setTimeout(()=>{ res(val) },ms) }) } function *fn(){ yield timeout(2000,1) console.log('222') yield timeout(3000,2) yield timeout(2000,3) return 2; }
使用while去讓上面的generator函數自執行瀏覽器
/* res.value自己是個異步的promise方法,若是幾個promise 有關聯那麼這樣就不行了 */ var f = fn(); var res = f.next(); while(!res.done) { res.value.then((val)=>{ console.log(val) }) res = f.next(); }
在瀏覽器可知打印的結果,並非順序的,1 3 是同以事件輸出的,2是最後輸出的app
咱們也可使用promise嵌套使其按順序輸出,可是這種並很差,由於可能不知道具體有幾個yield,嵌套的方式寫的很差看異步
var f = fn(); var res = f.next(); res.value.then((val)=>{ console.log(val) return res = f.next().value }).then((val)=>{ console.log(val) return res = f.next().value }).then((val)=>{ console.log(val) return res = f.next().value })
咱們定義一個generator自執行器(注爲何要提thunk函數,timeout已經通過thunk相似的封裝了)async
/* 寫一個適合generator的執行器 */ function *gn(){ let p1 = yield timeout(2000,1) console.log(p1) let p2 = yield timeout(3000,2) console.log(p2) let p3 = yield timeout(2000,3) console.log(p3) return 2; } // 按順序輸出 1 2 3 /* 傳入要執行的gen */ /* 其實循環遍歷全部的yeild (函數的遞歸) 根絕next返回值中的done判斷是否執行到最後一個, 若是是最後一個則跳出去*/ function run(fn) { var gen = fn(); function next(data) { /* 執行gen.next 初始data爲undefined */ var result = gen.next(data) /* 若是result.done 爲true 則表明執行到了gen的return,直接跳出去 */ if(result.done) { return; } /* result.value 爲promise */ result.value.then(val=>{ next(val) }) } /* 調用上一個next方法 */ next(); } run(gn)
上述輸出結構,分別是 1 2 3 ,間隔時間 2s 3s 2s異步編程
雖然已經有async和await這樣的generator的語法糖了,可是咱們仍是需瞭解如下他們的本質。相信您瞭解了本質,掌握asycn和await更不在話下函數
文章參考地址,阮一峯老師的 Generator 函數的異步應用 http://es6.ruanyifeng.com/#docs/generator-asyncthis