通常當你需要處理多個非同步操作,且這些操作之間有依賴關係時,使用 async 函數和 await 非常有用,下面有幾個使用情境:
在這些情境下,使用 async 函數和 await 讓程式碼結構更加清晰,使得非同步操作看起來更像同步操作,提高了程式碼的可讀性和可維護性。
因為async function會回傳一個promise,等到這個promise做完之後才會回傳原本裡面要傳遞的東西,像是資料或是錯誤訊息。把一個async function存到一個變數裡,跟其他的同步程序放在一起,想要像處理一個普通函式那樣,其實是會遇到困難的,因為實際上這個變數裡就只是一個promise。
async function delayedPrint() {
await delay(1000);
return "1sec passed";
}
console.log("start"); //想像是其他同步的程序
const result = delayedPrint();
console.log(result); //試圖將async function視為普通函式處理
console.log("end"); //另外的同步程序
像是要把一個壓縮檔案解開的感覺,我們要對這個async function的回傳作處理,怎麼處理一個promise呢?沒錯!就是then()/catch()或是async & await。
下面用一個pseudo code(假的程式碼)來演繹一下會發生什麼事,用一個async function fetchData來打api以獲得資料,接著對這個async function的回傳作處理,這邊分為以promise chaining和使用另一個async & await。
async function fetchData() {
try {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
return data; // 這個值將成為已解析的 Promise 的解析值
} catch (error) {
throw new Error('Failed to fetch data: ' + error.message); // 這個錯誤將成為被拒絕的 Promise 的拒絕理由
}
}
// 以then和catch使用 async 函數
console.log('這個console.log代表一些sync的程式...')
fetchData()
.then(data => {
console.log('Data fetched successfully:', data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
若是要利用另一個async函式來處理,會變這樣:
async function fetchDataAndHandleErrors() {
try {
let data = await fetchData();
console.log('Data fetched successfully:', data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
但因為我們馬上就會執行這個函式,使用async函式的目的也不是為了複用,其實用一個立即執行函式來作會更理想一些:
//一個立即執行的async函式
(async function () {
try {
let data = await fetchData();
console.log('Data fetched successfully:', data);
} catch (error) {
console.error('Error fetching data:', error);
}
})();
其實今天的例子舉的不是太好,只能概念性地想像當非同步程序與一般同步程序寫在一起時的樣子,但實際應用上應該會時常處理類似的情境。
udemy-The Complete Javascript Course