- Published on
[學習筆記] JS 非同步處理:Promise 建構函式與物件方法
Promise 物件是為了解決非同步事件的問題,像是一個等待非同步操作完成的物件,事件完成時,Promise 會根據操作結果是成功或失敗來做後續的相應處理。
狀態改變之後就會被固定,永遠不會再改變
最早的 JS 非同步語法 XMLHttpRequest
的可讀性很差,函式會是巢狀的結構,Promise 就是用來優化非同步的語法,而最常見的實踐就是 fetch()
web api,他讓非同步語法結構類似於同步語言,更好讀也更好管理。
Promise 的建構函式
Promise 本身是一個建構函式,使用 new Promise()
來建立物件。
Promise 物件的參數為一個包含兩個參數 (resolve, reject)
的 callback function,成功的狀況下就會執行 resolve(value)
,失敗則執行 reject(error)
,像是在 callback 裡面自己執行 if/else
。
new Promise( (resolve, reject) ⇒ { … } )
resolve 和 reject 都有一個回傳值,可以把 resolve 後的值透過 .then
繼續傳遞下去,reject 的回傳值則通常是錯誤訊息。
Promise.all()
和 Promise.race()
函式本身是物件的一種,因此 Promise 建構函示也有自己的方法可以使用,這邊介紹兩個比較常用、也容易被拿來比較的兩個方法:Promise.all()
和 Promise.race()
這兩個 Promise 物件方法,都是可以讓多個 Promise 同時進行。差別在於回傳值,以及是否一定會將所有的 Promise 跑完。
Promise.all()
會在所有的 Promise 都結束之後才回傳,回傳值是一個陣列,而且如果有任一個 Promise 被拒絕,Promise.all()
就會失敗
而 Promise.race()
會在任一個 Promise 有回傳值時(不論是成功或失敗),就結束整個行程,忽略掉其他的 Promise
Promise.all()
- 可以讓多個 promise 同時開始進行,但回傳值會依原本順序呈現
- 接收一個可迭代的物件做為參數,通常是 promise 物件組成的陣列
- 會依序在每個 promise 完成時,將 resolve 的值存入陣列中
- 所有的 promise 都 resolve 才會回傳 resolve 陣列,若其中有一個 promise 被拒絕,整個 Promise.all 就會被拒絕
const promise1 = Promise.resolve(1)
const promise3 = 2
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve(3), 1000)
})
Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log('所有 Promise 都已完成:', values) // [1, 2, 3]
})
.catch((error) => {
console.error('至少有一個 Promise 失敗:', error)
})
Promise.race()
- 同樣接收一個可迭代的物件做為參數
- 任何一個 promise 狀態改變(最早轉變的),就會回傳該 promise 物件成功或失敗的訊息 (resolve 或 reject)
- 有接收到回傳值後,其餘 promise 的結果或錯誤都會被忽略
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise 1 完成'), 2000)
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Promise 2 完成'), 1000)
})
Promise.race([promise1, promise2])
.then((result) => {
console.log('最快完成的 Promise:', result) // Promise 2 完成
})
.catch((error) => {
console.error('至少有一個 Promise 失敗:', error)
})
Promise 物件的方法
Promise 建構出的物件有三個方法,是讓我們可以在 Promise 結束之後繼續執行後續的動作,這三個方法必須在 new
出一個 Promise 物件後才能呼叫
then()
:Promise 執行結果是 resolve 的話就會接續執行.then()
裡的程式catch()
:如果執行結果是 reject,就會跳到 catch 繼續執行finaly()
:不論成功或失敗都會回傳
可以把 Promise 執行後的回傳值當作 then 的參數,在 then()
的程式就可以使用該值,catch()
也可以接收參數使用,參數通常是 event
const fetchData = () => {
return new Promise((resolve, reject) => {
// 用 setTimeout 模擬非同步
setTimeout(() => {
const data = { message: 'Hello, world!' }
resolve(data)
}, 2000)
})
}
// 使用 Promise
fetchData()
.then((result) => {
console.log('成功:', result)
})
.catch((error) => {
console.error('失敗:', error)
})
除了 Promise 之外,JS 還有許多處理非同步事件的方法,包括現在最常用的 async/await,這就等之後有機會再來筆記啦~
參考資料: