TypeScript 中的非同步/等待

TypeScript 中的非同步/等待

本文解釋了 TypeScript 中的非同步/等待。

YouTube Video

TypeScript 中的非同步/等待

async 是 TypeScript 中用來簡潔描述非同步操作的關鍵字,其行為與 JavaScript 的 async/await 語法相似。async 函數旨在使處理返回 Promise 的函數更加直觀。

async 函數的基礎

使用 async 關鍵字聲明的函數總是返回一個 Promise。以下是一個基本範例:。

1async function fetchData(): Promise<string> {
2    return "Data received";
3}
4
5fetchData().then((data) => console.log(data)); // "Data received"

在此範例中,由於 async 函數總是返回一個 Promise,因此返回值自動使用 Promise.resolve 進行解析。換句話說,"Data received" 變成了 Promise<string> 並被視為非同步操作。

await 關鍵字

await 關鍵字只能用於 async 函數內。這提供了一種能力,可以在繼續函數執行之前暫停並等待 Promise 的結果。

在以下範例中,使用 fetch 的非同步處理是以 async/await 的方式編寫的。

 1async function getUserData() {
 2    try {
 3        const response = await fetch("https://codesparklab.com/json/example.json");
 4        const data = await response.json();
 5        console.log(data);
 6    } catch (error) {
 7        console.error("Error fetching user data:", error);
 8    }
 9}
10
11getUserData();

在此範例中,await 用於等待 fetch 函數返回的 Promise 完成,其結果賦值給變數 response。此外,response.json() 的結果也使用 await 進行等待。

使用 async/await 的錯誤處理

非同步處理過程中發生的錯誤可使用標準的 try...catch 語法捕獲。如果在 await 的部分發生錯誤,該錯誤會在 catch 區塊中處理。

 1async function fetchDataWithErrorHandling() {
 2    try {
 3        const response = await fetch('https://invalid.codesparklab.com/');
 4        if (!response.ok) {
 5            throw new Error(`HTTP error! status: ${response.status}`);
 6        }
 7        const data = await response.json();
 8        console.log(data);
 9    } catch (error) {
10        console.error("Fetch error:", error);
11    }
12}
13
14fetchDataWithErrorHandling();

在上面的範例中,fetch 函數的結果是使用 await 等待的,如果發生錯誤,則用 try...catch 處理。

async/await 的優勢

  1. 直觀的非同步處理:通過使用 async/await,比起使用 Promise 鏈(thencatch),程式的流程更加直觀,可以像同步處理一樣編寫。

  2. 簡化錯誤處理:使用 try...catch 簡化了非同步操作中的錯誤處理。比起使用 Promise 鏈,可以撰寫出更具可讀性的代碼。

async 函數的返回值

一個 async 函式總是返回一個 Promise。因此,即使沒有明確返回 Promise,透過使用 async 關鍵字也可以進行非同步處理。

1async function example() {
2    return 42;
3}
4
5example().then((result) => console.log(result)); // 42

在上述程式碼中,傳回了一個同步值 42,但因為它在 async 函式內,所以會自動轉換成 Promise.resolve(42)

非同步函式的順序執行

依次執行多個非同步函式時,可以使用 await 來控制它們的順序。

 1async function fetchData(url: string): Promise<any> {
 2    try {
 3        const response = await fetch(url);
 4        return await response.json();
 5    } catch (error) {
 6        console.error("Error fetching user data:", error);
 7    }
 8}
 9
10async function fetchData1(): Promise<any> {
11    return await fetchData("https://codesparklab.com/json/example.json");
12}
13
14async function fetchData2(): Promise<any> {
15    return await fetchData("https://codesparklab.com/json/example2.json");
16}
17
18async function processData() {
19    const data1 = await fetchData1();
20    console.log(data1);
21
22    const data2 = await fetchData2();
23    console.log(data2);
24}
25
26processData();

在此範例中,會等待 fetchData1 完成後再執行 fetchData2。相較於使用 Promise 鍊,這種方式更具可讀性。

並行執行

如果希望並行執行非同步操作,可以使用 Promise.all 同時處理多個 Promise

 1async function fetchData(url: string): Promise<any> {
 2    try {
 3        const response = await fetch(url);
 4        return await response.json();
 5    } catch (error) {
 6        console.error("Error fetching user data:", error);
 7    }
 8}
 9
10async function fetchData1(): Promise<any> {
11    return await fetchData("https://codesparklab.com/json/example.json");
12}
13
14async function fetchData2(): Promise<any> {
15    return await fetchData("https://codesparklab.com/json/example2.json");
16}
17
18async function fetchMultipleData() {
19    const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
20    console.log(data1);
21    console.log(data2);
22}
23
24fetchMultipleData();

在這種情況下,fetchData1fetchData2 會同時執行,並在兩者都完成後繼續處理。這可以高效地處理多個非同步操作。

總結

  • 一個 async 函式會返回一個 Promise,透過使用 await 關鍵字,可以等待非同步操作的結果。
  • 透過使用 try...catch,非同步操作的錯誤處理變得更加簡單。
  • 透過使用 Promise.all,可以並行執行多個非同步操作。

async/await 在 TypeScript 和 JavaScript 中被廣泛使用,因為它可以更簡潔地描述非同步操作。

您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。

YouTube Video