es6 generator函數,我們都知道asycn和await是generator函數的語法糖,那麼genertaor怎麼樣才能實現asycn和await的功能呢? 1.thunk函數 將函數替換成一個只接受回調函數作為參數的單參數函數 2.generator非同步編程的示例 使用while去讓上面 ...
es6 generator函數,我們都知道asycn和await是generator函數的語法糖,那麼genertaor怎麼樣才能實現asycn和await的功能呢?
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非同步編程的示例
/* 非同步執行方法 */ 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是最後輸出的
我們也可以使用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類似的封裝了)
/* 寫一個適合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-async