[Medium] 📄 Promise
什麼是 Promise?
Promise 是 ES6 的新特性,主要是用來解決 callback hell 的問題,並且讓程式碼更容易閱讀。Promise 代表一個非同步操作的最終完成或失敗,以及其結果值。
Promise 有三種狀態:
- pending(進行中):初始狀態
- fulfilled(已完成):操作成功完成
- rejected(已拒絕):操作失敗
基本用法
建立 Promise
const myPromise = new Promise((resolve, reject) => {
// 非同步操作
const success = true;
if (success) {
resolve('成功!'); // 將 Promise 狀態改為 fulfilled
} else {
reject('失敗!'); // 將 Promise 狀態改為 rejected
}
});
myPromise
.then((result) => {
console.log(result); // '成功!'
})
.catch((error) => {
console.log(error); // '失敗!'
});
實際應用:處理 API 請求
// 建立一個共用 function 來處理 api 請求
function fetchData(url) {
return fetch(url)
.then((response) => {
// 檢查 response 是否落在 200 ~ 299 的區間
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json(); // 將 response 轉成 json,並回傳
})
.catch((error) => {
// 檢查網路是否異常,或者請求被拒絕
console.log('There has been a problem with your fetch operation:', error);
throw error; // 將錯誤拋出
});
}
fetchData('https://jsonplaceholder.typicode.com/users/1')
.then((userData) => {
console.log('User data received:', userData);
})
.catch((error) => {
console.log('Error:', error.message);
});
Promise 的方法
.then() / .catch() / .finally()
promise
.then((result) => {
// 處理成功的情況
return result;
})
.catch((error) => {
// 處理錯誤
console.error(error);
})
.finally(() => {
// 無論成功或失敗都會執行
console.log('Promise 完成');
});
Promise.all()
當所有 Promise 都完成時才會完成,只要有一個失敗就會失敗。
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve) =>
setTimeout(() => resolve('foo'), 100)
);
const promise3 = Promise.resolve(42);
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values); // [3, 'foo', 42]
});
使用時機:需要等待多個 API 請求都完成後才繼續執行。
Promise.race()
回傳第一個完成(無論成功或失敗)的 Promise 結果。
const promise1 = new Promise((resolve) =>
setTimeout(() => resolve('一號'), 500)
);
const promise2 = new Promise((resolve) =>
setTimeout(() => resolve('二號'), 100)
);
Promise.race([promise1, promise2]).then((value) => {
console.log(value); // '二號'(因為較快完成)
});
使用時機:設定請求超時、只取最快回應的結果。
Promise.allSettled()
等待所有 Promise 完成(無論成功或失敗),回傳所有結果。
const promise1 = Promise.resolve(3);
const promise2 = Promise.reject('錯誤');
const promise3 = Promise.resolve(42);
Promise.allSettled([promise1, promise2, promise3]).then((results) => {
console.log(results);
// [
// { status: 'fulfilled', value: 3 },
// { status: 'rejected', reason: '錯誤' },
// { status: 'fulfilled', value: 42 }
// ]
});
使用時機:需要知道所有 Promise 的執行結果,即使某些失敗也要繼續處理。
Promise.any()
回傳第一個成功的 Promise,所有都失敗才會失敗。
const promise1 = Promise.reject('錯誤 1');
const promise2 = new Promise((resolve) =>
setTimeout(() => resolve('成功'), 100)
);
const promise3 = Promise.reject('錯誤 2');
Promise.any([promise1, promise2, promise3]).then((value) => {
console.log(value); // '成功'
});
使用時機:多個備用資源,只要有一個成功即可。