前一篇我們講了Promise ,今天來把剩下的async function/await
講完。
還記得這張圖嗎?
從Callback 變成 Promise,我們讓code變的:
Callback Hell
那既然Promise這麼棒了,為什麼ES7還要再出一個async function/await
呢?
遇到不懂的趕快先去MDN 找一下資料:
The
async function
declaration creates a binding of a new async function to a given name. Theawait
keyword is permitted within the function body, enabling asynchronous, promise-based behavior to be written in a cleaner style and avoiding the need to explicitly configure promise chains.
小小抱怨一下,MDN繁體中文版本的回答真的讓人一言難盡…
首先我要先修正一下自己的觀念,async function/await
的本質是 promise 的語法糖,它可以讓我們的Promise 程式碼的可讀性大大提升。
這句話怎麼說呢?我們來看一下兩者對於同一個功能寫法上的差異吧:
Promise:
const apiURL = `https://webdev.alphacamp.io/api/lyrics/Coldplay/Yellow.json`
function fetchResourceWithPromise(url) {
return fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('There was a problem:', error);
});
}
fetchResourceWithPromise(apiURL);
Async function/await:
const apiURL = `https://webdev.alphacamp.io/api/lyrics/Coldplay/Yellow.json`
async function fetchResourceWithAsyncAwait(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('There was a problem:', error);
}
}
fetchResourceWithAsyncAwait(apiURL);
對於一個剛接觸非同步觀念的新手來說,Async function/await
的方式會讓我更好理解,主要原因就在於 Async function/await
將 then
的串鏈轉換成了直接的 await
,減少了縮排和區塊的視覺干擾,較能在閱讀時專注於程式本身的邏輯。
接下來讓我們認識Async function/await
async function
可以用來定義一個非同步函式,讓這個 function 本體是屬於非同步,但其內部以“同步的方式運行非同步”程式碼。
我們只需要在定義 function 前加上 async
就可以使用 async function:
async function asyncFn() {
return 'a';
}
asyncFn()
一般來說,任何一個function裡面如果有return 都是會回傳return後面的值:
function asyncFn() {
return 'a';
}
console.log(asyncFn());
那如果是async function
呢?
我們來看看如果把async function
console出來會是什麼:
async function asyncFn() {
return 'a';
}
console.log(asyncFn());
由於是以非同步的方式運行,因此我們無法得到 a 這個回傳值,但是我們得到了一個與 Promise 結構相似的函式,因此我們可以得知:
當async function
被呼叫時會回傳一個Promise 物件。
這個 Promise 物件代表著當 asyncFn
非同步執行完成後,它的結果值會是 'a'
。你可以使用 .then
來處理這個 Promise,以獲取最終的結果值。
asyncFn().then(result => {
console.log(result); // 'a'
});
雖然我完全沒有用過這個語法就是了XD
await
是屬於一元運算子,它會直接回傳後方表達式的值。
雖然是運算子,但是在原始碼中直接運行 await
則會出現錯誤,它只能在 async function
中運行,所以 async function/await
基本上是一體的,不會單獨出現。
另外await
工作還未完成,就不會跑後面的程式碼,這樣的寫法使程式碼看起來更像我們前面提到的:async function
本體是屬於非同步,但其內部以“同步的方式運行非同步”
在 async function/await
中的錯誤處理是使用 try...catch...
:
async function asyncFn() {
try {
const value = await somePromise();
return value;
} catch (err) {
console.log('Oops, there was an error :(');
}
}
asyncFn()
將正常情況下要執行的程式碼直接置入於 try
流程內,當遇到例外的錯誤時則撰寫在 catch
區塊內。
簡單的介紹一下,建議大家可以點擊下方的參考資料,觀看卡斯伯大大的文章,會更全面的了解。
但是必需再強調一次,async function/await
的本質是 promise 的語法糖,並不是一種全新的語法,因此了解promise 以及「非同步處理」觀念本身要很清楚,採用 async/await 目的是讓程式變好讀。
「仔細判讀程式流程」的基礎功一定要做紮實,程式流程沒想清楚,光是鑽研語法不足以解決問題,甚至可能會失焦。 By ALPHA Camp
參考資料:
https://www.casper.tw/development/2020/10/16/async-await/
https://pjchender.dev/javascript/js-async-await/