async/await

ES7的async/await語法在2016年就已經(jīng)提出來了,慚愧的是我最近才接觸使用者冤,肤视,下面來聊聊

解決了什么問題

在async/await之前,我們有三種方式寫異步代碼

  1. 嵌套回調(diào)

  2. 以Promise為主的鏈式回調(diào)

  3. 使用Generators

但是涉枫,這三種寫起來都不夠優(yōu)雅邢滑,ES7做了優(yōu)化改進,async/await應運而生愿汰,async/await相比較Promise 對象then 函數(shù)的嵌套困后,與 Generator 執(zhí)行的繁瑣(需要借助co才能自動執(zhí)行,否則得手動調(diào)用next() )衬廷, Async/Await 可以讓你輕松寫出同步風格的代碼同時又擁有異步機制摇予,更加簡潔,邏輯更加清晰吗跋。

async/await特點

  1. async/await更加語義化侧戴,async 是“異步”的簡寫,async function 用于申明一個 function 是異步的跌宛; await酗宋,可以認為是async wait的簡寫, 用于等待一個異步方法執(zhí)行完成秩冈;

  2. async/await是一個用同步思維解決異步問題的方案(等結(jié)果出來之后本缠,代碼才會繼續(xù)往下執(zhí)行)

  3. 可以通過多層 async function 的同步寫法代替?zhèn)鹘y(tǒng)的callback嵌套

async function語法

  • 自動將常規(guī)函數(shù)轉(zhuǎn)換成Promise,返回值也是一個Promise對象

  • 只有async函數(shù)內(nèi)部的異步操作執(zhí)行完入问,才會執(zhí)行then方法指定的回調(diào)函數(shù)

  • 異步函數(shù)內(nèi)部可以使用await

async function name([param[, param[, ... param]]]) { statements }
name: 函數(shù)名稱丹锹。
param:  要傳遞給函數(shù)的參數(shù)的名稱
statements: 函數(shù)體語句。
返回值: 返回的Promise對象會以async function的返回值進行解析芬失,或者以該函數(shù)拋出的異常進行回絕楣黍。

image

await語法

  • await 放置在Promise調(diào)用之前,await 強制后面點代碼等待棱烂,直到Promise對象resolve租漂,得到resolve的值作為await表達式的運算結(jié)果

  • await只能在async函數(shù)內(nèi)部使用,用在普通函數(shù)里就會報錯

[return_value] = await expression;

expression:  一個 Promise  對象或者任何要等待的值。

返回值:返回 Promise 對象的處理結(jié)果。如果等待的不是 Promise 對象哩治,則返回該值本身秃踩。

image

錯誤處理

在async函數(shù)里,無論是Promise reject的數(shù)據(jù)還是邏輯報錯业筏,都會被默默吞掉,所以最好把await放入try{}catch{}中憔杨,catch能夠捕捉到Promise對象rejected的數(shù)據(jù)或者拋出的異常

function timeout(ms) {

  return new Promise((resolve, reject) => {

    setTimeout(() => {reject('error')}, ms);  //reject模擬出錯,返回error

  });

}

async function asyncPrint(ms) {

  try {

     console.log('start');

     await timeout(ms);  //這里返回了錯誤

     console.log('end');  //所以這句代碼不會被執(zhí)行了

  } catch(err) {

     console.log(err); //這里捕捉到錯誤error

  }

}

asyncPrint(1000);

如果不用try/catch的話蒜胖,也可以像下面這樣處理錯誤(因為async函數(shù)執(zhí)行后返回一個promise)

function timeout(ms) {

  return new Promise((resolve, reject) => {

    setTimeout(() => {reject('error')}, ms);  //reject模擬出錯消别,返回error

  });

}

async function asyncPrint(ms) {

  console.log('start');

  await timeout(ms)

  console.log('end');  //這句代碼不會被執(zhí)行了

}

asyncPrint(1000).catch(err => {

    console.log(err); // 從這里捕捉到錯誤

});

如果你不想讓錯誤中斷后面代碼的執(zhí)行台谢,可以提前截留住錯誤寻狂,像下面

function timeout(ms) {

  return new Promise((resolve, reject) => {

    setTimeout(() => {

        reject('error')

    }, ms);  //reject模擬出錯,返回error

  });

}

async function asyncPrint(ms) {

  console.log('start');

  await timeout(ms).catch(err => {  // 注意要用catch

console.log(err) 

  })

  console.log('end');  //這句代碼會被執(zhí)行

}

asyncPrint(1000);

使用場景

多個await命令的異步操作朋沮,如果不存在依賴關系(后面的await不依賴前一個await返回的結(jié)果)蛇券,用Promise.all()讓它們同時觸發(fā)

function test1 () {
    return new Promise((resolve, reject) => {

        setTimeout(() => {

            resolve(1)

        }, 1000)

    })

}

function test2 () {

    return new Promise((resolve, reject) => {

        setTimeout(() => {

            resolve(2)

        }, 2000)

    })

}

async function exc1 () {

    console.log('exc1 start:',Date.now())

    let res1 = await test1();

    let res2 = await test2(); // 不依賴 res1 的值

    console.log('exc1 end:', Date.now())

}

async function exc2 () {

    console.log('exc2 start:',Date.now())

    let [res1, res2] = await Promise.all([test1(), test2()])

    console.log('exc2 end:', Date.now())

}

exc1();

exc2();

exc1 的兩個并列await的寫法,比較耗時朽们,只有test1執(zhí)行完了才會執(zhí)行test2

你可以在瀏覽器的Console里嘗試一下怀读,會發(fā)現(xiàn)exc2的用Promise.all執(zhí)行更快一些

image

兼容性

image

在自己的項目中使用

通過 babel 來使用诉位。

只需要設置 presets 為 stage-3 即可骑脱。

安裝依賴:

npm install babel-preset-es2015 babel-preset-stage-3 babel-runtime babel-plugin-transform-runtime

修改.babelrc:

 "presets": ["es2015", "stage-3"],

 "plugins": ["transform-runtime"]

這樣就可以在項目中使用 async 函數(shù)了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苍糠,一起剝皮案震驚了整個濱河市叁丧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌岳瞭,老刑警劉巖拥娄,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瞳筏,居然都是意外死亡稚瘾,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門姚炕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摊欠,“玉大人,你說我怎么就攤上這事柱宦⌒┙罚” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵掸刊,是天一觀的道長免糕。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么石窑? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任牌芋,我火速辦了婚禮,結(jié)果婚禮上松逊,老公的妹妹穿的比我還像新娘姜贡。我一直安慰自己,他們只是感情好棺棵,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布楼咳。 她就那樣靜靜地躺著,像睡著了一般烛恤。 火紅的嫁衣襯著肌膚如雪母怜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天缚柏,我揣著相機與錄音苹熏,去河邊找鬼。 笑死币喧,一個胖子當著我的面吹牛轨域,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播杀餐,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼干发,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了史翘?” 一聲冷哼從身側(cè)響起枉长,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎琼讽,沒想到半個月后必峰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡钻蹬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年吼蚁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片问欠。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡肝匆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出溅潜,到底是詐尸還是另有隱情术唬,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布滚澜,位于F島的核電站粗仓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜借浊,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一塘淑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蚂斤,春花似錦存捺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至纽窟,卻和暖如春肖油,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背臂港。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工森枪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人审孽。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓县袱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親佑力。 傳聞我的和親對象是個殘疾皇子式散,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345