JavaScript 的 async/await : async 和 await 在干什么

回調(diào)函數(shù) ===> Promise 對象 ===> Generator 函數(shù)

JavaScript 的 async/await

async 和 await 在干什么

async 是“異步”的簡寫,而 await 可以認(rèn)為是 async wait 的簡寫。
async 用于申明一個 function 是異步的膳音,而 await 用于等待一個異步方法執(zhí)行完成卫旱。
await 只能出現(xiàn)在 async 函數(shù)中芦鳍。

async 起什么作用

async function testAsync() {
    return "hello async";
}

const result = testAsync();
console.log(result);
image.png

——輸出的是一個 Promise 對象各拷。

c:\var\test> node --harmony_async_await .
Promise { 'hello async' }

async 函數(shù)返回的是一個 Promise 對象形病。

參考文檔: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function

async 函數(shù)(包含函數(shù)語句磷脯、函數(shù)表達(dá)式蛾找、Lambda表達(dá)式)會返回一個 Promise 對象,如果在函數(shù)中 return 一個直接量赵誓,async 會把這個直接量通過 Promise.resolve() 封裝成 Promise 對象打毛。

async 函數(shù)返回的是一個 Promise 對象柿赊,所以在最外層不能用 await 獲取其返回值的情況下,我們當(dāng)然應(yīng)該用原來的方式:then()鏈來處理這個 Promise 對象幻枉,就像這樣

testAsync().then(v => {
    console.log(v);    // 輸出 hello async
});

Generator 生成器函數(shù)

顧名思義碰声,它是一個生成器,它也是一個狀態(tài)機(jī)熬甫,內(nèi)部擁有值及相關(guān)的狀態(tài)胰挑,生成器返回一個迭代器Iterator對象,我們可以通過這個迭代器椿肩,手動地遍歷相關(guān)的值瞻颂、狀態(tài),保證正確的執(zhí)行順序郑象。

image.png

如上代碼贡这,定義了一個showWords的生成器函數(shù),調(diào)用之后返回了一個迭代器對象(即show)

調(diào)用next方法后厂榛,函數(shù)內(nèi)執(zhí)行第一條yield語句盖矫,輸出當(dāng)前的狀態(tài)done(迭代器是否遍歷完成)以及相應(yīng)值(一般為yield關(guān)鍵字后面的運算結(jié)果)

每調(diào)用一次next,則執(zhí)行一次yield語句击奶,并在該處暫停辈双,return完成之后,就退出了生成器函數(shù)正歼,后續(xù)如果還有yield操作就不再執(zhí)行了.

換言之辐马,next 方法的作用是分階段執(zhí)行 Generator 函數(shù)。每次調(diào)用 next 方法局义,會返回一個對象喜爷,表示當(dāng)前階段的信息( value 屬性和 done 屬性)。value 屬性是 yield 語句后面表達(dá)式的值萄唇,表示當(dāng)前階段的值檩帐;done 屬性是一個布爾值,表示 Generator 函數(shù)是否執(zhí)行完畢另萤,即是否還有下一個階段湃密。

function* showWords() {
    yield 'one';
    yield 'two';
    return 'three';
}

var show = showWords();

調(diào)用 Generator 函數(shù)丽涩,會返回一個內(nèi)部指針(即遍歷器 )g 入挣。這是 Generator 函數(shù)不同于普通函數(shù)的另一個地方色冀,即執(zhí)行它不會返回結(jié)果造垛,返回的是指針對象。調(diào)用指針 g 的 next 方法纵苛,會移動內(nèi)部指針(即執(zhí)行異步任務(wù)的第一段)铣卡,指向第一個遇到的 yield 語句奢赂,上例是執(zhí)行到 'three'為止铺厨。

image.png
image.png
image.png

Generator 函數(shù)缎玫,依次讀取兩個文件硬纤。

var fs = require('fs');

var gen = function* (){
  var f1 = yield readFile('/etc/fstab');
  var f2 = yield readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

寫成 async 函數(shù),就是下面這樣赃磨。

var asyncReadFile = async function (){
  var f1 = await readFile('/etc/fstab');
  var f2 = await readFile('/etc/shells');
  console.log(f1.toString());
  console.log(f2.toString());
};

其中筝家,readFile 函數(shù)定義如下:

var readFile = function (fileName){
  return new Promise(function (resolve, reject){
    fs.readFile(fileName, function(error, data){
      if (error) reject(error);
      resolve(data);
    });
  });
};

一比較就會發(fā)現(xiàn),async 函數(shù)就是將 Generator 函數(shù)的星號(*)替換成 async邻辉,將 yield 替換成 await溪王,僅此而已。

async 函數(shù)的實現(xiàn)

async 函數(shù)的實現(xiàn)恩沛,就是將 Generator 函數(shù)和自動執(zhí)行器在扰,包裝在一個函數(shù)里缕减。

async function fn(args){
  // ...
}

等同于

function fn(args){ 
  return spawn(function*() {
    // ...
  }); 
}

所有的 async 函數(shù)都可以寫成上面的第二種形式雷客,其中的 spawn 函數(shù)就是自動執(zhí)行器。

下面給出 spawn 函數(shù)的實現(xiàn)桥狡,基本就是前文自動執(zhí)行器的翻版搅裙。

function spawn(genF) {
  return new Promise(function(resolve, reject) {
    var gen = genF();
    function step(nextF) {
      try {
        var next = nextF();
      } catch(e) {
        return reject(e); 
      }
      if(next.done) {
        return resolve(next.value);
      } 
      Promise.resolve(next.value).then(function(v) {
        step(function() { return gen.next(v); });      
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}

async 函數(shù)是非常新的語法功能,新到都不屬于 ES6裹芝,而是屬于 ES7部逮。目前,它仍處于提案階段嫂易,但是轉(zhuǎn)碼器 Babel 和 regenerator 都已經(jīng)支持兄朋,轉(zhuǎn)碼后就能使用。

yield與異步

函數(shù)在遇到y(tǒng)ield后暫停運行怜械,我們可以在需要的地方使用next讓它繼續(xù)運行颅和。并且必要時可以使用next傳入?yún)?shù)。

yield 關(guān)鍵字用來暫停和繼續(xù)一個生成器函數(shù)缕允。我們可以在需要的時候控制函數(shù)的運行峡扩。

yield 關(guān)鍵字使生成器函數(shù)暫停執(zhí)行,并返回跟在它后面的表達(dá)式的當(dāng)前值障本。與return類似教届,但是可以使用next方法讓生成器函數(shù)繼續(xù)執(zhí)行函數(shù)yield后面內(nèi)容,直到遇到y(tǒng)ield暫图菟或return返回或函數(shù)執(zhí)行結(jié)束案训。

for…of

for…of循環(huán)可以自動遍歷Generator函數(shù)時生成的Iterator對象。

function* ge() { 
  yield '1';
  yield '2';
  yield '3';
  return '4';
}
for(let v of ge()){
  alert(V);    // 1 2 3 4
}

Kotlin 開發(fā)者社區(qū)

國內(nèi)第一Kotlin 開發(fā)者社區(qū)公眾號粪糙,主要分享强霎、交流 Kotlin 編程語言、Spring Boot猜旬、Android脆栋、React.js/Node.js倦卖、函數(shù)式編程、編程思想等相關(guān)主題椿争。

開發(fā)者社區(qū) QRCode.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怕膛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子秦踪,更是在濱河造成了極大的恐慌褐捻,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件椅邓,死亡現(xiàn)場離奇詭異柠逞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)景馁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門板壮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人合住,你說我怎么就攤上這事绰精。” “怎么了透葛?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵笨使,是天一觀的道長。 經(jīng)常有香客問我僚害,道長硫椰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任萨蚕,我火速辦了婚禮靶草,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘门岔。我一直安慰自己爱致,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布寒随。 她就那樣靜靜地躺著糠悯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妻往。 梳的紋絲不亂的頭發(fā)上互艾,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機(jī)與錄音讯泣,去河邊找鬼纫普。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昨稼。 我是一名探鬼主播节视,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼假栓!你這毒婦竟也來了寻行?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤匾荆,失蹤者是張志新(化名)和其女友劉穎拌蜘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牙丽,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡简卧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了烤芦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片举娩。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拍棕,靈堂內(nèi)的尸體忽然破棺而出晓铆,到底是詐尸還是另有隱情勺良,我是刑警寧澤绰播,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站尚困,受9級特大地震影響蠢箩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜事甜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一谬泌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逻谦,春花似錦掌实、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至滋将,卻和暖如春邻悬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背随闽。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工父丰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掘宪。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓蛾扇,卻偏偏與公主長得像攘烛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子镀首,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容