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 語法可以更直觀地寫出 Promise。async 函式總是返回一個 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 頻道。