理解async函數(shù)就要先理解generator函數(shù),因為async就是Generator函數(shù)的語法糖
十載的蘭西網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。全網(wǎng)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整蘭西建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)從事“蘭西網(wǎng)站設(shè)計”,“蘭西網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。
Generator 函數(shù)是 ES6 提供的一種異步編程解決方案,可以先理解為一個狀態(tài)機(jī),封裝了多個內(nèi)部狀態(tài),執(zhí)行Generator函數(shù)返回一個遍歷器對象,通過遍歷器對象,可以依次遍歷 Generator 函數(shù)內(nèi)部的每一個狀態(tài)
語法上,Generator 函數(shù)是一個普通函數(shù),但是有兩個特征。
一是,function關(guān)鍵字與函數(shù)名之間有一個星號;
二是,函數(shù)體內(nèi)部使用yield表達(dá)式,定義不同的內(nèi)部狀態(tài)(yield在英語里的意思就是“產(chǎn)出”);
function* helloGenerator() {
yield 'hello'
yield 'Generator'
return 'ending'
}
let Generator = helloGenerator()
調(diào)用Generator函數(shù)后并不執(zhí)行,返回的也不是函數(shù)運行結(jié)果而是一個指向內(nèi)部狀態(tài)的指針對象,也就是遍歷器對象(Iterator Object)。
必須調(diào)用遍歷器對象的next方法,使得指針移向下一個狀態(tài)。
console.log(Generator.next()) // {value: 'hello', done: false}
console.log(Generator.next()) // {value: 'Generator', done: false}
console.log(Generator.next()) // {value: 'ending', done: true}
第一次調(diào)用next方法,Generator函數(shù)開始執(zhí)行,直到遇到y(tǒng)ield表達(dá)式為止。next方法返回一個對象,value屬性就是當(dāng)前yield表達(dá)式的值hello,done屬性的值false,表示遍歷還沒有結(jié)束。
第二次調(diào)用next方法,Generator 函數(shù)從上次yield表達(dá)式停下的地方,一直執(zhí)行到下一個yield表達(dá)式
繼續(xù)調(diào)用next方法直到done屬性值為true或者執(zhí)行到return語句(如果沒有return語句就執(zhí)行到函數(shù)結(jié)束),表示遍歷已經(jīng)結(jié)束
如果再次調(diào)用next方法,此時Generator函數(shù)已經(jīng)運行完畢,next方法返回對象的value屬性為undefined,done屬性為true。以后再調(diào)用next方法,返回的都是這個值
可以理解為暫停的標(biāo)志,遇到y(tǒng)ield表達(dá)式,就暫停執(zhí)行后面的操作,并將緊跟在yield后面的那個表達(dá)式的值,作為返回的對象的value屬性值。yield表達(dá)式與return語句都能返回緊跟在語句后面的那個表達(dá)式的值。區(qū)別在于每次遇到y(tǒng)ield,函數(shù)暫停執(zhí)行,下一次再從該位置繼續(xù)向后執(zhí)行,而return語句不具備位置記憶的功能。一個函數(shù)里面,只能執(zhí)行一次return語句,但是可以執(zhí)行多次yield表達(dá)式。從另一個角度看,也可以說 Generator 生成了一系列的值,這也就是它的名稱的來歷(英語中,generator 這個詞是“生成器”的意思)。另外需要注意,yield表達(dá)式只能用在 Generator 函數(shù)里面,用在其他地方都會報錯。
next方法可以帶一個參數(shù),該參數(shù)就會被當(dāng)作上一個yield表達(dá)式的返回值
function* foo(x) {
let y = yield x + 1
let k = yield y + 2
yield k / 2
return k
}
let a = foo(1)
console.log(a.next()) // {value: 2, done: false}
console.log(a.next(3)) // {value: 5, done: false}
console.log(a.next(8)) // {value: 4, done: false}
console.log(a.next()) // {value: 8, done: true}
第一次運行next方法時,返回1+1的值2;第二次調(diào)用next方法,將上一次yield表達(dá)式的值設(shè)為3,y等于3,返回y + 2的值5;第三次調(diào)用next方法,將上一次yield表達(dá)式的值設(shè)為8,k等于8,返回k/2的值4
注意,由于next方法的參數(shù)表示上一個yield表達(dá)式的返回值,所以在第一次使用next方法時,傳遞參數(shù)是無效的。
除了next方法還有throw()、return()兩個方法,這三個方法本質(zhì)上是同一件事,可以放在一起理解。它們的作用都是讓 Generator 函數(shù)恢復(fù)執(zhí)行,并且使用不同的語句替換yield表達(dá)式。
next()是將yield表達(dá)式替換成一個值。
throw()是將yield表達(dá)式替換成一個throw語句。
const g = function* (x, y) {
let result = yield x + y;
return result;
};
const gen = g(1, 2);
gen.throw(new Error('出錯了')); // Uncaught Error: 出錯了
// 相當(dāng)于將 let result = yield x + y 替換成 let result = throw(new Error('出錯了'));
return()是將yield表達(dá)式替換成一個return語句。
gen.return(2); // {value: 2, done: true}
// 相當(dāng)于將 let result = yield x + y替換成 let result = return 2;
ES6提供了yield*表達(dá)式,用來在一個Generator函數(shù)里面執(zhí)行另一個Generator函數(shù)。
function* foo(x) {
yield 1
yield* bar()
yield 4
}
function* bar() {
yield 2
yield 3
}
let a = foo()
console.log(a.next()) // {value: 1, done: false}
console.log(a.next()) // {value: 2, done: false}
console.log(a.next()) // {value: 3, done: false}
console.log(a.next()) // {value: 4, done: false}
console.log(a.next()) // {value: undefined, done: true}
由于yield* bar()語句得到的值,是一個遍歷器,所以要用星號表示。運行結(jié)果就是使用一個遍歷器,遍歷了多個Generator函數(shù),有遞歸的效果。
yield*后面的 Generator 函數(shù)(沒有return語句時),等同于在 Generator 函數(shù)內(nèi)部,部署一個for...of循環(huán)。
ES7 中引入了 async/await,async 是一個通過異步執(zhí)行并隱式返回 Promise 作為結(jié)果的函數(shù)。async 函數(shù)的實現(xiàn)原理,就是將 Generator函數(shù)和自動執(zhí)行器,包裝在一個函數(shù)里。
根據(jù)阮一峰老師的介紹,async函數(shù)就是Generator函數(shù)的語法糖,并對Generator函數(shù)進(jìn)行了改進(jìn)。
上面代碼async函數(shù)就是將Generator函數(shù)的星號(*)替換成async,將yield替換成await,僅此而已
async函數(shù)對 Generator 函數(shù)的改進(jìn),體現(xiàn)在以下四點