Generator 函數(shù)是協(xié)程在 ES6 的實現(xiàn),最大特點就是可以交出函數(shù)的執(zhí)行權(quán)(即暫停執(zhí)行)。
function* gen(x){
var y = yield x+2
return y
}
var g = gen(1)
g.next() //{ value:3,done: false }
g.next() //{ value: undefined, done: true }
由于這個代碼是可以暫停執(zhí)行的,所以需要在函數(shù)名前面加個*號,其他地方跟普通函數(shù)沒啥區(qū)別。
執(zhí)行g(shù)en函數(shù),會返回一個對象,對象中有一個next()函數(shù),調(diào)用這個函數(shù),會得到兩個參數(shù),value表示 yield 后面語句的值,done表示這個函數(shù)是否執(zhí)行完畢。
我的理解就是:實際上 yield相當于一個標記點 這個函數(shù)被yield 分成了兩個階段,當調(diào)用next()的時候 ,函數(shù)就會運行到標記點的位置,并且返回標記點第一個階段的狀態(tài)(yield 后面語句的值,以及是否還有下一個階段)。
next 方法返回值的 value 屬性,是 Generator 函數(shù)向外輸出數(shù)據(jù);next 方法還可以接受參數(shù),這是向 Generator 函數(shù)體內(nèi)輸入數(shù)據(jù)。
function* gen(x){
var y = yield x + 2;
return y;
}
var g = gen(1);
g.next() // { value: 3, done: false }
g.next(2) // { value: 2, done: true }
next() 可以接受一個參數(shù),這個參數(shù)會被當成上一階段的異步任務的返回結(jié)果被函數(shù)體內(nèi)的變量y接受。所以g.next(2)輸出的value是2。
Generator 函數(shù)內(nèi)部還可以部署錯誤處理代碼,捕獲函數(shù)體外拋出的錯誤。
function* gen(x){
try {
var y = yield x + 2;
} catch (e){
console.log(e);
}
return y;
}
var g = gen(1);
g.next();
g.throw('出錯了');
// 出錯了
上面代碼的最后一行,Generator 函數(shù)體外,使用指針對象的 throw 方法拋出的錯誤,可以被函數(shù)體內(nèi)的 try ... catch 代碼塊捕獲。
使用 Generator 函數(shù),執(zhí)行一個真實的異步任務。
var fetch = require('node-fetch'); //返回一個Promise對象
function* gen(){
var url = 'https://api.github.com/users/github';
var result = yield fetch(url);
console.log(result.bio);
}
var g = gen();
var result = g.next(); //得到的是 fetch(url)(Promise對象)
result.value.then(function(data){
return data.json();
}).then(function(data){
g.next(data);
});