generator異步調用原理

generator是一個狀態(tài)保存機,每次遇到y(tǒng)ield會停止,需要調用next函數(shù)來執(zhí)行

function * test1(){
  yield 3+2
  console.log('a')
  yield 7
  return 5
}
let t = test1()
t.next()//{value:5,done:false}
t.next()//a,{value:7,done:false}
t.next()//{value:5,done:true}

而yield返回的值是無法直接捕捉到的

function * test1(){
  let a = 8+(yield 3+2)
  console.log(a)
}
let t = test()
t.next()//{value:5,done:false}
t.next()//NaN,{value:undefined,done:true}

因為yield不會賦值給左邊a,永遠等于undefined,8+undefined就返回NaN了,
而在next函數(shù)中傳值可以等于賦值給上一個yield的結果

function * test1(){
  let a = 8+(yield 3+2)
  console.log(a)
}
let t = test()
t.next()//{value:5,done:false}
t.next(6)//14,{value:undefined,done:true}

這一次我們第二次給next傳值6,則a = 8 + 6 =14,我們沒寫return,默認return為undefined,所以value為undefined

thunk函數(shù)

thunk函數(shù)起源于函數(shù)的求值方式

function add(a,b)
變成
addThunk(a)(b)

一個readFile的thunk可以這么寫

var Thunk = function (fn) {
    return function (...args) {
        return function (callback) {
            return fn.call(this, ...args, callback)
        }
    }
}

var readFileThunk = Thunk(fs.readFile)
readFileThunk('./1.txt')(function(err,data){})

這是一種惰性求值方式,但是結合generator卻很好地控制流程,原因是可以把函數(shù)和它的回調抽離出來,如果我們在把回調抽象成一個函數(shù),集中處理這個next指針,那么寫法就和同步代碼無異了

這樣的話,next指針在上一個函數(shù)的回調里執(zhí)行,因此只有上一個異步調用返回以后才會繼續(xù)往下執(zhí)行。

function run(fn) {
    var gen = fn();
    function next(err, data) {
        var result = gen.next(data);   
        if (result.done) return;
        result.value(next);
    }
    next();
}
var g = function* () {
    var f1 = yield readFileThunk('./1.txt');
    console.log(f1.toString());
    var f2 = yield readFileThunk('./2.txt');
    console.log(f2.toString());
    var fn = yield readFileThunk('./3.txt');
};

run(g);

上面的next函數(shù),實際就是我們抽離出來控制next指針的

第一次執(zhí)行,調用run函數(shù),傳入g函數(shù),執(zhí)行后返回gen
調用next(),err和data均為undefined,此時result為{value:function readFileThunk('./1.txt'),done:false}

然后再調用result.value(next),就把next函數(shù)繼續(xù)放入回調中


第二次:
readFileThunk('./1.txt')返回結果,此時調用上一步的回調函數(shù)next,傳入err和data,在gen.next傳入data,那么上一步返回的結果就為data,因此f1就為讀取1.txt的結果,它通過在下一次回調中,把結果通過gen.next傳回去實現(xiàn)的。

基本就是這種方式實現(xiàn)異步控制的,關鍵就是控制權的處理上

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容