前端開發:Async/Await的使用心得
接著三掌櫃的上一篇關於Promise的使用的博文來繼續講,前端處理非同步回撥操作用到的方法之一:Async/Await。可以說Async/Await是Promise的升級版,而且應用了Async/Await的非同步請求的情況下,可以讓程式碼看起來像同步方式呼叫解決非同步回撥。
在ES7之前,瞭解到Promise是ES6為了解決非同步回撥而產生的解決方案,避免出現回撥地獄(Callback Hell),那麼ES7為什麼又提出了新的Async/Await標準?問題答案就是:Promise雖然解決了非同步巢狀的怪圈,使用表達清晰的鏈式表達;但是如果在實際開發過程中有些地方有大量的非同步請求的時候,而且流程複雜巢狀的情況下,檢查相關程式碼會發現一個比較尷尬。
一、Async/Await是什麼?
Async/Await是基於Promise而來的,Async/Await是相互依存的,缺一不可,它們的出現就是為了Promise而來,也算是Promise的進化改良版,為的就是解決文章開始說的如果出現大量複雜巢狀不易讀的Promise非同步問題。
1、Async/Await基本含義
①Async/Await是基於Promise實現的,是寫非同步程式碼的新方式,它們不能用於普通的回撥函式;
②Async/Await也是非阻塞的;
③Async/Await的寫法使得非同步程式碼看起來像同步程式碼,簡潔、便於讀取。
2、Async/Await的語法
async必須宣告的是一個function函式,await就必須是在async宣告的函式內部使用,這是一個固定搭配,任何一種不符合這兩個條件,程式就會報錯,具體舉例項來直觀看一下:
let data = 'data'
a = async function () {
const b = function () {
await data
}
}
二、Async/Awaitd的本質
1、 Async的本質
async是對generator的再一次語法糖封裝,幫助實現了生成器的呼叫,使語句更貼近同步程式碼的表達方式,可以將async函式看做是多個非同步操作封裝的 promise物件。
async宣告的函式的返回其實就是一個Promise,也就是說只要宣告的函式是async,不管內部怎麼處理,它返回的一定是一個Promise,舉個例子如下所示:
(async function () {
return 'Promis+++‘
})() // 返回的是Promise+++
2、 Awaitd的本質
await的本質其實是可以提供等同於“同步效果”的等待非同步返回能力的語法糖,也就是then的語法糖。如果想使用await來執行一個非同步操作,那麼其呼叫函式必須使用async來宣告。
await能返回一個Promise物件,也能返回一個值。若await返回的是Promise物件,那麼還可以繼續給await的返回值使用then函式。舉個例項看一下:
const a = async ()=>{
let message = '宣告值111’
let result = await message;
console.log('由於上面的程式還沒執行完,“等待一會”');
return result
}
a().then(result=>{
console.log('輸出',result);
})
三、 Async/Await的優勢
為什麼說Async/Awaitd比Promise更勝一籌?具體原因如下所示。
1、 簡潔明瞭
根據上述關於Async/Awaitd的例項可以看到,Async/Awaitd的寫法很簡單,相比Promise的寫法,不用寫.then,不用寫匿名函式處理Promise的resolve值,也不用定義多餘的data變數,更避免了巢狀程式碼的操作,大大省去了很多程式碼行,使得處理非同步操作的程式碼簡潔明瞭,方便查閱和精準定位。
2、 錯誤處理的方式
Async/Await可以讓try/catch同時處理同步和非同步的錯誤,而且在Promise中try/catch不能處理JSON.parse的錯誤,在Promise中需要使用.catch,但是錯誤處理的那坨程式碼會非常冗餘,要知道實際開發過程中程式碼會比理論上的情況會更復雜。
通過使用Async/Await,try/catch能處理JSON.parse的錯誤,具體例項如下所示:
const request = async () => {
try {
const data = JSON.parse(await getJSON())
console.log(data)
} catch (err) {
console.log(err)
}
}
3、 條件語句
通過使用Async/Await,可以使得條件語句寫法簡潔又可以提高程式碼可讀性,這裡就不再舉對比的例子,只舉一個Async/Await的使用例項來說:
const request = async () => {
const data = await getJSON()
if (data.anotherRequest) {
const moreData = await anotherRequest(data);
console.log(moreData)
return moreData
} else {
console.log(data)
return data
}
}
4、 中間值
在實際開發過程中會遇到這種場景:呼叫promise1,使用promise1返回的結果再去呼叫promise2,然後使用兩者的結果去呼叫promise3。在沒有使用Async/Await之前的寫法,應該是這樣的:
const request = () => {
eturn promise1()
.then(value1 => {
return promise2(value1)
.then(value2 => {
return promise3(value1, value2)
})
})
}
使用了Async/Await的寫法之後,是這樣的:
const request = async () => {
const value1 = await promise1()
const value2 = await promise2(value1)
return promise3(value1, value2)
}
通過上述兩個寫法,直觀的看出來使用Async/Await之後會使得程式碼變得非常整潔簡單,直觀,高可讀性。
5、 錯誤棧對比
如果例項中呼叫多個Promise,其中的一個Promise出現錯誤,Promise鏈中返回的錯誤棧沒有顯示具體的錯誤發生的位置資訊,這就造成排查錯誤的耗時時長和解決的難度,甚至會起到反作用,假設錯誤棧的唯一函式名為errorPromise,但是它和錯誤沒有直接關係。如果使用了Async/Await之後,錯誤棧會直接指向錯誤所在的函式,這樣更清晰直觀的方便排查問題所在,尤其是在檢視分析錯誤日誌的時候非常有效有用。
6、 除錯
通過上面描述的Async/Await優點中,一直在反覆強調Async/Await會使得程式碼簡潔明瞭,其實在除錯過程中,Async/Await也可以使得程式碼除錯起來很輕鬆簡單,相對於Promise來講,不用再寫太多箭頭函式,可以直接像除錯同步程式碼一樣單步走,跳過await語句。
7、 中斷/終止程式
首先要明確知道,Promise自身是不能終止的,Promise本身只是一個狀態機,儲存了三種狀態,一旦進行發出請求,就必須要閉環,無法進行取消操作,就算是在前面講到的pending狀態,也只是一個掛起請求的狀態,但不是取消。
但是使用Async/Await的時候,想要終止程式就很簡單,那是因為Async/Await語義化很明顯,和一般的function的寫法類似,想要終端程式的時候,直接return一個值(“”、null、false等)就可以了,實際上就是直接返回一個Promise。具體例項如下所示:
let count = 3;
const a = async ()=>{
const result = await delay(2000);
const result1 = await delaySecond(count);
if (count > 2) {
return '';
// return false;
// return null;
}
console.log(await delay(2000));
console.log(‘結束’);
};
a().then(result=>{
console.log(result);
})
.catch(err=>{
console.log(err);
})
async函式本質就是返回一個Promise。
四、實際開發過程中非同步操作需要注意的事項
Async/Await使用for迴圈獲取資料(序列)
根據上面Promise的for迴圈獲取資料來做對比,直接使用上述例項的場景,來看看Async/Await的寫法,具體操作如下所示:
(async ()=>{
array = [timeout(2000), timeout(1000), timeout(1000)]
for (var i=0; i < array.length; i++) {
result = await array[i]();
console.log(result);
}
})()
通過對比,在這裡還要誇一下Async/Await,直觀的可以看到同樣的需求,使用Async/Await來實現是不是非常的方便和簡潔。
以上就是本章全部內容,歡迎關注三掌櫃的微信公眾號“程式猿by三掌櫃”,三掌櫃的新浪微博“三掌櫃666”,歡迎關注!
https://www.361zimeiti.cn/402665.html |
https://www.361zimeiti.cn/402675.html |