ES6 生成器是一種順序旧乞、看似同步的異步流程控制表達風(fēng)格谅年,它可以打破代碼執(zhí)行的完整性括儒,試看下方代碼绕沈。
function foo(x,y) {
return (x+y);
}
var it = foo(1,2);
console.log(it); //3
function *foo(x,y) {
return (x+y);
}
var it = foo(1,2);
console.log(it);
var result = it.next();
console.log(result.value); //3
從中我可以知道這個生成器打破了代碼執(zhí)行的完整性。var it = foo()
這行代碼只是構(gòu)造了 it 一個迭代器帮寻,并沒有執(zhí)行生成器乍狐。真正執(zhí)行生成器的代碼是 var result = it.next();
- 生成器的聲明方式
1.function *foo() {}
2.function* foo() {}
3.function*foo() {}
下面介紹 生成器 具體使用
- 生成器提供了更強大更引人注目的內(nèi)建消息輸入輸出能力,通過 yield 和 next(..) 實現(xiàn)
function *foo(x) {
var y = x * (yield) * (yield);
return y;
}
var it = foo( 6 );
// 啟動foo(..)
it.next();
it.next(7);
var res = it.next( 8 );
console.log(res.value); //336
- iterable(可迭代):指該對象可以進行迭代操作固逗。
var arr = [1,2,3,4];
var it = arr[Symbol.iterator]();
console.log(it.next().value); //1
console.log(it.next().value); //2
console.log(it.next().value); //3
- 再論 yield
function *something() {
var setVal;
while(true) {
if(setVal == undefined) {
setVal = 1;
} else {
setVal = setVal*3+12;
}
yield setVal;
}
}
var it = something();
console.log(it.next().value); //1
console.log(it.next().value); //15
上述代碼使用 while(true)使函數(shù)能夠產(chǎn)生無限個數(shù)字序列浅蚪。若 while (true)沒有使用yield,循環(huán)會一直下去烫罩,這使得 while(true)在javascript 的使用減少惜傲,使用 yield 可以改善這一局面,當(dāng)執(zhí)行到 yield 時贝攒,返回到主程序中或者是循環(huán)隊列中盗誊。
- try...finally:如果在生成器內(nèi)有 try..finally 語句,它將總是運行隘弊,即使生成器已經(jīng)外部結(jié)束哈踱。
function *something() {
try{
var setVal;
while(true) {
if(setVal == undefined) {
setVal = 1;
} else {
setVal = setVal*3+12;
}
yield setVal;
}
} finally {
console.log("清理");
}
}
var it = something();
for (var val of it) {
console.log(val);
if (val > 200) {
console.log(it.return("val的值大于200了").value);
//此處不需要 break 來結(jié)束這個循環(huán)
}
}
調(diào)用 it.return(..) 之后,它會立即終止生成器梨熙,這當(dāng)然會運行 finally 語句开镣。另外,它還會把返回的 value 設(shè)置為傳入 return(..) 的內(nèi)容咽扇,這就是 "val的值大于200了" 被傳出去的過程⌒安疲現(xiàn)在我們也不需要包含 break 語句了陕壹,因為生成器的迭代器已經(jīng)被設(shè)置為done:true,所以 for..of 循環(huán)會在下一個迭代終止树埠。
- 生成器應(yīng)用于異步并發(fā)(生成器最閃光的地方就是可以實現(xiàn)異步)
function foo(x,y) {
ajax(
"http://some.url.1/?x=" + x + "&y=" + y,
function(err,data){
if (err) {
// 向*main()拋出一個錯誤
it.throw( err );
}
else {
// 用收到的data恢復(fù)*main()
it.next( data );
}
}
);
}
function *main() {
try {
var text = yield foo( 11, 31 );
console.log( text );
}
catch (err) {
console.error( err );
}
}
var it = main();
// 這里啟動糠馆!
it.next();
這段代碼的閃光點就是yield foo(11,31)
;當(dāng)我們執(zhí)行 foo ()函數(shù)的時候,返回 undefined弥奸,遇到 yield 的時候停頓了榨惠,其實就是在思考一個問題“應(yīng)該返回什么值給 text ”,回觀 foo ()盛霎,如果這個 Ajax 函數(shù)執(zhí)行成功的話,執(zhí)行 it.next()
,這會響應(yīng)數(shù)據(jù)恢復(fù)生成器耽装,意味著們暫停的 yield 表達式直接接收到了這個值愤炸。然后隨著生成器代碼繼續(xù)運行,這個值被賦給局部變量 text掉奄。從而實現(xiàn)異步操作规个。