es6 generator函數的異步編程

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

相關文章
相關標籤/搜索