JavaScript中的非同步/等待(async/await)
在本文中,我們將解釋JavaScript中的非同步/等待(async/await)。
YouTube Video
JavaScript中的非同步/等待(async/await)
JavaScript中的async(和await)是為了讓編寫非同步操作更加直觀且易讀而設計的功能。通過使用這個,可以減少傳統回呼函式和 Promise 鏈的複雜性,並且可以用類似同步程式碼的方式來撰寫非同步程式碼。
async函式
async用於將一個函式定義為非同步函式。一個async函式總是返回一個Promise。在標記為async的函式內,你可以使用await等待Promise的結果返回。
async函式的基本語法
1async function myAsyncFunction() {
2 // Write asynchronous processing here
3 return 'Result'; // Return a Promise
4}在這種情況下,呼叫myAsyncFunction()會自動返回一個Promise對象。當Promise被解析時,其結果成為return所返回的值。
範例:基本async函式
1async function greet() {
2 return 'Hello, World!';
3}
4
5greet().then((message) => {
6 console.log(message); // Displays "Hello, World!"
7});await
await用於等待Promise被解析。通過使用await,你可以暫停執行,直到Promise被解析並獲得Promise的結果。await只能在async函式內使用。
範例:如何使用await
1async function fetchData() {
2 // Wait for the result of the Promise
3 const data = await fetch('https://codesparklab.com/json/example.json');
4 // Wait for the asynchronous operation to complete
5 const jsonData = await data.json();
6 // Retrieve and display the data
7 console.log(jsonData);
8}
9
10fetchData();在上述範例中,透過await等待fetch函式返回的Promise,隨後使用結果進行進一步的非同步操作。
使用async/await進行錯誤處理
如果在async函式內發生錯誤,該錯誤會被視為Promise的reject。你可以使用try...catch語句來進行錯誤處理。
範例:錯誤處理
1async function fetchData() {
2 try {
3 // Invalid URL
4 const data = await fetch('https://invalid.codesparklab.com/');
5 const jsonData = await data.json();
6 console.log(jsonData);
7 } catch (error) {
8 // Catch the error
9 console.error('Failed to fetch data:', error);
10 }
11}
12
13fetchData();使用try...catch區塊可以捕獲非同步操作中發生的錯誤,避免程式在錯誤發生時崩潰。
async/await的優點
與傳統的 Promise 鏈相比,async/await 具有以下優點:。
- 可讀性提升
- 非同步處理可以像同步程式碼一樣書寫,避免了深層嵌套的
Promise鏈和回呼的複雜性。
- 非同步處理可以像同步程式碼一樣書寫,避免了深層嵌套的
- 更易於偵錯
- 由於程式碼類似同步程式碼,偵錯及錯誤處理變得更容易。
- 更高的維護性
- 非同步處理可以更簡單地書寫,使修改或更換程式碼更容易,提高了長期的可維護性。
範例:Promise 鏈 vs async/await
讓我們比較使用 Promise 鏈的程式碼與使用 async/await 的程式碼。
1// Code using Promise chains
2function fetchDataPromise() {
3 fetch('https://codesparklab.com/json/example.json')
4 .then((response) => response.json())
5 .then((data) => {
6 console.log(data);
7 })
8 .catch((error) => {
9 console.error('Failed to fetch data:', error);
10 });
11}
12
13// Code using async/await
14async function fetchDataAsync() {
15 try {
16 const response = await fetch('https://codesparklab.com/json/example.json');
17 const data = await response.json();
18 console.log(data);
19 } catch (error) {
20 console.error('Failed to fetch data:', error);
21 }
22}如你所見,使用 async/await 可讓你以直線式方式撰寫非同步處理,使程式碼更加易讀。
同時執行多個非同步操作
通過將 Promise.all() 或 Promise.race() 與 await 結合使用,可以同時執行多個非同步操作並集體處理其結果。
Promise.all()
1async function fetchMultipleData() {
2 try {
3 const [data1, data2] = await Promise.all([
4 fetch('https://codesparklab.com/json/example1.json'),
5 fetch('https://codesparklab.com/json/example2.json')
6 ]);
7 const jsonData1 = await data1.json();
8 const jsonData2 = await data2.json();
9 console.log(jsonData1);
10 console.log(jsonData2);
11 } catch (error) {
12 console.error('Failed to fetch data:', error);
13 }
14}
15
16fetchMultipleData();Promise.all()同時解析多個 Promise,並以數組形式返回它們的結果。它會等待所有的 Promise 被解析,如果其中任何一個失敗,則整體視為失敗。
Promise.race()
1async function fetchFastestData() {
2 try {
3 const fastestResponse = await Promise.race([
4 fetch('https://codesparklab.com/json/example1.json'),
5 fetch('https://codesparklab.com/json/example2.json')
6 ]);
7 const jsonData = await fastestResponse.json();
8 console.log('Fastest data:', jsonData);
9 } catch (error) {
10 console.error('Fetch error:', error);
11 }
12}
13
14fetchFastestData();Promise.race()會返回第一個完成(無論成功或失敗)的 Promise 的結果。當你想對最先完成的非同步操作做出回應時,這會非常有用。然而,如果第一個 Promise 失敗,錯誤會立刻被catch捕捉到。
Promise.allSettled()
1async function fetchWithAllSettled() {
2 const results = await Promise.allSettled([
3 // This URL will success
4 fetch('https://codesparklab.com/json/example1.json'),
5 // This URL will fail
6 fetch('https://invalid.codesparklab.com/')
7 ]);
8
9 results.forEach((result, index) => {
10 if (result.status === 'fulfilled') {
11 const url = result.value.url;
12 console.log(`Request ${index + 1} succeeded:`, url);
13 } else {
14 const reason = result.reason;
15 console.warn(`Request ${index + 1} failed:`, reason);
16 }
17 });
18}
19
20fetchWithAllSettled();Promise.allSettled()會等待所有的結果,不論是成功還是失敗。每個結果會以{ status, value }或{ status, reason }的形式返回,使你可以判斷哪些 Promise 成功、哪些失敗。
Promise.any()
1async function fetchAnySuccessful() {
2 try {
3 const firstSuccessful = await Promise.any([
4 // This URL will fail
5 fetch('https://invalid.codesparklab.com/'),
6 // This URL will success
7 fetch('https://codesparklab.com/json/example1.json')
8 ]);
9 const jsonData = await firstSuccessful.json();
10 console.log('First successful response:', jsonData);
11 } catch (error) {
12 console.error('All fetch requests failed:', error);
13 }
14}
15
16fetchAnySuccessful();Promise.any()只會返回第一個成功完成的 Promise 的結果。只有當所有的 Promises 都失敗時,才會拋出異常。在某些 API 不太穩定的情況下,它可以作為重試機制使用,直到其中一個成功為止。
總結
async函數:總是返回一個 Promise,用於編寫非同步處理。await:用於等待 Promise 被解析並接收其結果。- 錯誤處理:使用
try...catch處理非同步處理過程中出現的錯誤。 - 多個非同步操作:透過使用像是
Promise.all()這樣的方法,你可以同時執行多個非同步任務。
async/await 是處理非同步處理的強大工具,務必善用它們以簡化複雜的非同步邏輯。
您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。