背景
前端頁面中經(jīng)常會(huì)遇到需要發(fā)起異步請(qǐng)求后,要等到異步請(qǐng)求返回結(jié)果才能執(zhí)行某個(gè)操作的需求,如果不了解promise和async await等JS異步調(diào)用的實(shí)現(xiàn)方式,就可能寫出一些較為奇怪的代碼。例如,promise和async await混用等現(xiàn)象。
弄清callback、Promise、async await的區(qū)別很重要
- callback 、Promise 和 async await三者都是異步編程解決方案。
- callback 比較常見不需解釋,是基于ES5語法規(guī)范的。
- Promise 在語法上是一個(gè)對(duì)象(準(zhǔn)確說是一個(gè)構(gòu)造函數(shù),用來生成Promise實(shí)例。),是基于ES6語法規(guī)范的。
- async await是基于ES7語法規(guī)范的,。
幾個(gè)使用異步時(shí)經(jīng)常出現(xiàn)的幾個(gè)場(chǎng)景
1、Promise和async await混用

image.png
- 這類錯(cuò)誤最常見,混用是由于不清楚Promise 和 async await兩者的區(qū)別所致。
- 使用async await的目的多數(shù)情況下是為了讓我們的異步代碼看起來更像同步的,易于閱讀與理解。
- async 函數(shù)會(huì)隱式地返回一個(gè)promise,該promise的reosolve值就是函數(shù)return的值。
- 所以,正確的寫法要么改成使用promise形式,要么使用async await形式
1.1、改成promise形式

image.png
- 通過then來處理成功時(shí)返回的數(shù)據(jù)信息,通過catch來處理失敗的信息。
1.2、改成使用async await的形式,如下

image.png
2、不知道await后面跟的是不是promise對(duì)象
- await只能出現(xiàn)在async函數(shù)中。
- 如果不是 promise, await會(huì)阻塞后面的代碼,先執(zhí)行async外面的同步代碼,同步代碼執(zhí)行完,再回到async- 內(nèi)部,把這個(gè)同步函數(shù)的返回值作為達(dá)式的結(jié)果。
- 如果是 promise, await 也會(huì)暫停async后面的代碼,先執(zhí)行async外面的同步代碼,等著 Promise 對(duì)象 fulfilled,然后把 resolve 的參數(shù)作為 await 表達(dá)式的運(yùn)算結(jié)果。
2.1、不確定await后面是不是promise對(duì)象,但是報(bào)錯(cuò)了,我怎么捕獲
-
可以直接使用 try catch來捕獲異常。如下圖
image.png
2.2、確定await后面就是promise對(duì)象,捕獲異常
-
可以直接使用promise的catch方法捕獲異常。如下圖
image.png - 該種情形下也可以采用try catch的形式
3、多個(gè)請(qǐng)求需要發(fā)出,互相之間沒有返回值依賴關(guān)系
3.1、并發(fā)請(qǐng)求需要全部成功才能繼續(xù)執(zhí)行

image.png
- 就用promise.all即可,將所有要發(fā)出的請(qǐng)求整理成數(shù)組,每一個(gè)請(qǐng)求都是一個(gè)promise。
3.2、并發(fā)請(qǐng)求中某個(gè)請(qǐng)求失敗,但不能影響整體邏輯執(zhí)行

image.png
- 上圖的寫法是某個(gè)請(qǐng)求的失敗可以繼續(xù)執(zhí)行業(yè)務(wù)的情況。
兩種情況的區(qū)別在于,有無catch處理單個(gè)異常
4、多個(gè)請(qǐng)求要發(fā)出,之間有返回值的相互依賴關(guān)系(即第一個(gè)請(qǐng)求返回值是第二個(gè)請(qǐng)求的入?yún)?,以此類推?/h5>
4.1、使用promise形式實(shí)現(xiàn)
image.png
- 上圖為使用promise形式實(shí)現(xiàn)的多個(gè)請(qǐng)求串行調(diào)用后的范式。
- 有人可能會(huì)問,為什么使用promise的方式可以一直.then下去,這是因?yàn)?,第一個(gè)then返回的是一個(gè)新的- - - promise對(duì)象,第二個(gè)then等待這個(gè)新返回的promise對(duì)象的狀態(tài)變化而變化,如果新對(duì)象的狀態(tài)變?yōu)閞esolved,就調(diào)用第二個(gè)then的第一個(gè)回調(diào)函數(shù),如果狀態(tài)變?yōu)閞ejected,就調(diào)用第二個(gè)then的第二個(gè)回調(diào)函數(shù)。
4.2、使用async await形式實(shí)現(xiàn)
image.png
- 上圖為使用async await的范式。
以上幾種情況為經(jīng)常收到業(yè)務(wù)同學(xué)詢問的典型情景,其余情形待后續(xù)補(bǔ)充。
相比于promise, async await 的優(yōu)點(diǎn)
- 當(dāng)多個(gè)接口間有返回值依賴關(guān)系時(shí),使用async await可以讓代碼簡(jiǎn)潔,不需要像Promise那樣需要寫then,避免了代碼嵌套。

image.png

image.png
以上幾種情況為經(jīng)常收到業(yè)務(wù)同學(xué)詢問的典型情景,其余情形待后續(xù)補(bǔ)充。

