概要
在很長一段時間里面,FE們不得不依靠回調來處理異步代碼。使用回調的結果是,代碼變得很糾結,不便於理解與維護,值得慶幸的是Promise帶來了.then(),讓代碼變得井然有序,便於管理。於是我們大量使用,代替了原來的回調方式。但是不存在一種方法可以讓當前的執行流程阻塞直到promise完成。JS里面,我們無法直接原地等promise完成,唯一可以用於提前計划promise完成后的執行邏輯的方式就是通過then附加回調函數。 現在隨着Async/Await的增加,可以讓接口按順序異步獲取數據,用更可讀,可維護的方式處理回調。
What Is Async/Await
Async/Await是一個期待已久的JavaScript特性,讓我們更好的理解使用異步函數。它建立在Promises上,並且與所有現有的基於Promise的API兼容。那么下面我來學習下這兩個函數吧,lets go~
1、Async—聲明一個異步函數(async function someName(){...})
- 自動將常規函數轉換成Promise,返回值也是一個Promise對象
- 只有async函數內部的異步操作執行完,才會執行then方法指定的回調函數
- 異步函數內部可以使用await
2、Await—暫停異步的功能執行(var result = await someAsyncCall();)
- 放置在Promise調用之前,await強制其他代碼等待,直到Promise完成並返回結果
- 只能與Promise一起使用,不適用與回調
- 只能在async函數內部使用
3、使用小貼士:async函數完全可以看作多個異步操作,包裝成的一個 Promise 對象,而await命令就是內部then命令的語法糖。
How To Use Async/Await
如何來用呢?我們一起來敲一敲代碼吧~
1、async 函數的幾種使用形式


2、await的用法則相對簡單了許多,他后面需要是一個Promise對象,如果不是則會被轉成Promise對象。只要其中一個如果Promise對象變為reject狀態,那么整個async函數都會中斷操作。如果狀態是resolve,那么他的返回值則會變成then里面的參數,如下。

3、使用小貼士
- 怎樣容錯呢,猶豫await后面的promise運行結果可能是rejected,最好把await放入try{}catch{}中
- Await后的異步操作,如果彼此沒有依賴關系最好同時觸發,在下面場景一會有介紹
- Await只能在async函數之中,如果在普通函數中,會報錯
使用場景介紹
那么什么情況下適合用,什么情況下不適合使用呢?
1、場景一,我們同時發出三個不互相依賴的請求,如果用Async/Await就顯得不明智了

如上圖所示,上面我們A需要2s,B需要4s,C需要3s,我們如上圖所示發請求,就存在彼此依賴的關系,c等b執行完,b等a執行完,從開始到結束需要(2+3+4)9s。
此時我們需要用Promise.all()將異步調用並行執行,而不是一個接一個執行,如下所示:

這樣將會節省我們不少的時間,從原來的的9s縮減到4s,是不是很開心,耶~
2、場景二,我曾經遇到過一個場景,一個提交表單的頁面,里面有姓名、地址等巴拉巴拉的信息,其中有一項是手機驗證碼,我們不得不等待手機驗證碼接口通過,才能發出后續的請求操作,這時候接口之間就存在了彼此依賴的關系,Async跟Await就有了用武之地,讓異步請求之間可以按順序執行。
其中不用Async/Await的寫法,我們不得不用.then()的方式,在第一個請求驗證碼的接口有返回值之后,才能執行后續的的Promise,並且還需要一個then輸出結果,如下圖:

而用Async/Await的方式去寫就是下面這樣,我們將邏輯分裝在一個async函數里。這樣我們就可以直接對promise使用await了,也就規避了寫then回調。最后我們調用這個async函數,然后按照普通的方式使用返回的promise。要記得容錯呢~~

以上是兩個模擬簡單的場景,為的是讓大家容易理解Async/Await的使用,那么接下來我們看看兼容性吧~
兼容性
Async / Await已經在大多數主流瀏覽器中可用。

小結
Async/Await讓我們用少量的代碼來使用Promise,我們可以將一些有依賴關系的回調函數的處理邏輯放在async里面,然后在非async的區域使用,這樣可以減少then或者catch回調。
