JavaScript 中的 Promise 類

JavaScript 中的 Promise 類

在本文中,我們將解釋 JavaScript 中的 Promise 類。

YouTube Video

Promise

Promise 類用於處理非同步操作。當操作成功時處理結果,若操作失敗則進行錯誤處理。傳統上,當需要等待非同步操作完成時會使用回呼函式,但透過 Promise 可以更清晰且更強大地實現。

1const promise = new Promise((resolve, reject) => {
2    setTimeout(() => resolve("Done!"), 1000);
3});
4
5// Displays "Done!" after 1 second
6promise.then(result => console.log(result));
  • 此程式碼是一個非同步處理的範例,能在一秒後顯示「Done!」。
    • 首先,使用 new Promise 創建一個新的 Promise 物件。參數是一個接受兩個回呼函式的函數:resolve 代表成功,reject 代表失敗。
    • 透過 setTimeout 在一秒後呼叫 resolve()
    • promise 物件的 then() 方法會等待其完成,並顯示結果。

基本結構

Promise 是一個最終會發生成功失敗結果的物件。

 1const promise = new Promise((resolve, reject) => {
 2    // Asynchronous operation
 3    // Flag indicating whether the operation was successful
 4    const success = true;
 5
 6    if (success) {
 7        resolve('Operation successful!');
 8    } else {
 9        reject('An error occurred');
10    }
11});
  • 如果成功,則會呼叫 resolve()
  • 如果失敗,則會呼叫 reject()

Promise 物件有三種狀態。

1promise
2    .then((result) => {
3        console.log(result);
4    })
5    .catch((error) => {
6        console.error(error);
7    })
  • 未決定
    • 非同步處理尚未完成。
  • 已成功
    • 非同步處理已成功,且結果已由 resolve() 返回。可以透過 then() 方法取得結果。
  • 已拒絕
    • 非同步處理失敗,並且已經透過 reject() 傳回錯誤。可以透過 catch() 方法獲取錯誤。

then()catch() 方法

通過使用 Promise,您可以定義在非同步操作完成後要執行的操作。為此,您可以使用 then()catch() 方法。

then()

1const promise = new Promise((resolve, reject) => {
2    resolve('Operation successful!');
3});
4
5promise.then((result) => {
6    console.log(result);  // "Operation successful!"
7});
  • then() 方法指定在 Promise 成功時要調用的函式。

catch()

1const promise = new Promise((resolve, reject) => {
2    reject('An error occurred');
3});
4
5promise.catch((error) => {
6    console.error(error);  // "An error occurred"
7});
  • catch() 方法指定在 Promise 失敗時要調用的函式。

finally() 方法

 1const promise = new Promise((resolve, reject) => {
 2    resolve('Operation successful!');
 3});
 4
 5promise
 6    .then((result) => {
 7        console.log(result);
 8    })
 9    .catch((error) => {
10        console.error(error);
11    })
12    .finally(() => {
13        console.log('The operation has completed');
14    });
  • finally() 方法定義了無論 Promise 成功或失敗都會在最後執行的程式碼。

「then()」鏈式調用

then() 會返回一個新的 Promise,因此你可以鏈式調用下一個 then()

 1const promise = new Promise((resolve, reject) => {
 2    setTimeout(() => {
 3        resolve(1);
 4    }, 1000);
 5});
 6
 7promise
 8    .then(result => {
 9        console.log(result); // 1
10        return result + 1;
11    })
12    .then(result => {
13        console.log(result); // 2
14        return result + 1;
15    })
16    .then(result => {
17        console.log(result); // 3
18    })
19    .catch(error => {
20        console.error(error.message); // Something went wrong
21    });
  • 在這段程式碼中,最初的 resolve() 傳遞值 1,每個 then 返回的值都會傳遞到下一個 then
  • 使用 catch(),你可以在一個地方處理鏈式調用中發生的所有錯誤。

實用範例

例如,Promises 常用於從伺服器獲取資料。讓我們來看一個使用 fetch() API 的範例。

 1fetch('https://codesparklab.com/json/example.json')
 2    .then(response => {
 3        if (!response.ok) {
 4            throw new Error('Network error');
 5        }
 6        return response.json();
 7    })
 8    .then(data => {
 9        console.log(data);
10    })
11    .catch(error => {
12        console.error('Error:', error);
13    });
  • 在這段程式碼中,由於 fetch() 會返回一個 Promise,所以使用 then() 在收到伺服器的回應後處理資料。錯誤使用 catch() 處理。

處理多個 Promise

Promise.all()

要同時執行多個 Promise,並且僅在它們都成功時繼續,請使用 Promise.all()

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.resolve(2);
 3const promise3 = Promise.resolve(3);
 4
 5Promise.all([promise1, promise2, promise3])
 6    .then((results) => {
 7        console.log(results);  // [1, 2, 3]
 8    })
 9    .catch((error) => {
10        console.error('Error :', error);
11    });
  • 僅當所有 Promise 都成功時才會調用 then()。如果有一個失敗,則會調用 catch()

Promise.allSettled()

如果你想要同時執行多個 Promise,並在不論成功或失敗的情況下取得所有結果,可以使用 Promise.allSettled()

 1const promise1 = Promise.resolve(1);
 2const promise2 = Promise.reject("Failed");
 3const promise3 = Promise.resolve(3);
 4
 5Promise.allSettled([promise1, promise2, promise3])
 6    .then((results) => {
 7        results.forEach(result => console.log(result));
 8        // [
 9        //   { status: 'fulfilled', value: 1 },
10        //   { status: 'rejected', reason: 'Failed' },
11        //   { status: 'fulfilled', value: 3 }
12        // ]
13    });
  • 當所有的 Promise 都已結束(無論是完成還是拒絕)時,then() 會被呼叫。每個結果都包含一個 status 屬性('fulfilled' 或 'rejected')。即使有些失敗,也不會影響其他操作。

Promise.race()

Promise.race() 會返回最先完成(無論是成功還是失敗)的 Promise 的結果。

1const promise1 = new Promise((resolve) => setTimeout(resolve, 100, 'First'));
2const promise2 = new Promise((resolve) => setTimeout(resolve, 500, 'Second'));
3
4Promise.race([promise1, promise2]).then((result) => {
5    console.log(result);  // "First"
6});
  • 如本例所示,返回第一個完成的 Promise 的結果。

async/await 的關係

使用 async/await 語法可以更直觀地寫出 Promiseasync 函式總是返回一個 Promise,而 await 則會等待該 Promise 解決。

 1async function fetchData() {
 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 :', error);
 8    }
 9}
10
11fetchData();

通過這種方式使用 async/await,可以像寫同步程式碼一樣撰寫非同步操作,從而使代碼更易於閱讀。

總結

  • Promise 是用於處理非同步操作成功或失敗的物件。
  • 使用 then() 處理成功的操作,使用 catch() 處理錯誤。
  • finally() 定義了無論成功或失敗都會在最後執行的代碼。
  • 您可以使用 Promise.all()Promise.race() 一起處理多個 Promise
  • async/await 是更簡單撰寫 Promise 的語法。

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

YouTube Video