Promise
在程式中非常好用,是因為很多操作都需要使用到非同步的概念,而要處理非同步,除了使用callback function
之外,就是會使用Promise
。
這篇講述我是如何理解這個概念。
今天主要講Promise
的狀態跟呼叫。
Promise
是一個constructor function
,假如需要自己寫一個Promise
時,語法如下:
const promise = new Promise((resolve, reject) => {
resolve(value);
reject(error);
});
它的參數resolve
以及reject
是它自己所提供的callback
,不用自己額外寫,而這兩個的名稱可以自己定義像是:
const promise = new Promise((a, b) => {
a();
b();
});
效果也一樣,但是不建議這麼做。
而會設定這兩個參數,是有它的意義存在,從承諾來談吧。
可以把它想像成一個承諾,答應了某件事情,不管最後有沒有成功,都會有一個結果。
所以兩個參數的意義在於,成功跟失敗時會獲得什麼結果,所以當程式正在進行一個Promise
的非同步時,如果成功就會呼叫resolve
如果失敗就會呼叫reject
,這裡要注意的是假設已經呼叫成功的結果了,那就回不去還沒決定的狀態,這是不可逆的,成功以及失敗只能選一個,回傳了這個結果之後,Promise
就會結束。
最初的時候,是未確認的狀態,也就是pending
,接著成功的話會變成Fulfilled
的狀態,失敗就會是Rejected
。
舉例來說,小白跟小紅告白了。
前情提要,因為promise
的特性一定得非同步的方式進行,代表著被告白的時候,就算遇到白馬王子,也沒辦法馬上秒答應,同樣的就算遇到非心儀對象,也不能馬上送出一張好人卡。
也就代表說,使用了promise
的狀態,任何人都會一模一樣的以非同步的方式
一致得到結果,像是小白也不會以同步的方式
馬上被拒絕,這種藉由讓大家用統一的方式處理非同步就是promise
的好處之一,而接下來小白就要開始行動了,讓我們看下去。
小白: 「我喜歡妳!」 => promise事件開始,現在狀態是pending。
小紅: 「let me think think.」 => 非同步開始排隊等待了,答案醞釀。
小白: 「你慢慢想!」 => 等待非同步時間結束。
--- 兩天後 ---
小紅: 「deserving of better people.」=> 被拒絕,現在狀態是rejected。
小白: 「......」 => 小白catch到了這個reject。
小紅: 「you are friends forever.」=> 小紅傳入rejected函式。
小白: 「好吧,那就還是朋友。」 => 小白知道回不去了(狀態不可逆)。
當寫好了一個Promise
,裡面已經定義好了失敗以及成功的結果後,但要取出這些結果,還需要一些方法,主要如下:
把上面的例子寫成程式:
const mission = new Promise((resolve, reject) => {
setTimeout(() => {
reject("you are friends forever");
}, 200);
});
mission.catch((answer) => {
console.log(answer); //you are friends forever
});
then
會捕獲成功的結果,catch
則相反是失敗的,像是在這邊就可以利用catch
去抓到reject
裡面的函式。
使用then
時會捕獲成功的結果,語法會像這樣:
promise.then(
(result) =>{},
(error)=> {}
);
第一個參數是成功的結果,第二個參數是失敗的,所以也可以用then
去抓失敗的結果,像是這樣:
const mission = new Promise((resolve, reject) => {
setTimeout(() => {
reject("you are friends forever");
}, 200);
});
mission.then(
(result) => console.log(result),
(error) => console.log(error)
); // you are friends forever
最後一個是Finally
,這個方式不會有任何參數,因為不需要,可以用這個方式來確認整個promise
已經結束了。
const mission = new Promise((resolve, reject) => {
setTimeout(() => {
reject("you are friends forever");
}, 200);
});
mission
.then(
(result) => console.log(result),
(error) => console.log(error)
)
.finally(() => {
console.log("小白:一切都已經結束了");
});
// you are friends forever
// 小白:一切都已經結束了
執行的函式最後一定會回傳值,就算沒有寫也是回傳undefined
,而在Promise
來說,設計Promise
物件最後的結果要不是回傳一個成功的值,不然就是失敗的值, fulfilled
或是rejected
,最後再複習一次,Promise
的狀態只會有這三種。
就算是非同步,也是有需要一個接著一個執行的狀況,其實Promise
後面也是能繼續連著Promise
的,就是所謂的Promises chaining
,明天的文章主題,明天見。
[1] 淺談 JavaScript 的 Promise
[2] MDN - Promise
[3] 你今天 Promise 了嗎?