0%

Promise - Promise 運作概念

文章目的

簡單介紹一下 Promise 的運作,了解運作後,對於使用 Promise 一定會有相當的幫助。

Promise 狀態

Promise 在運作過程中會經歷不同的狀態,每個狀態都會有它獨特的地方,我們現在就來看看吧。

  1. pending(未確認狀態):Promise 一開始的狀態,尚未得到任何結果。

  2. fulfilled(已實現的狀態):Promise 完成的狀態,會透過 resolve 作為參數回傳結果,並透過 then 來接收結果。

  3. rejected(已否決的狀態): Promise 否決的狀態,會透過 reject 作為參數回傳結果(用在串 api 時通常會是 api 的錯誤訊息),可以透過 catch 來接收結果。

fulfilled 跟 rejected 又通稱為 settled(已確認狀態),當 Promise 運行時,一次只會接收一個 settled,若想要重新接收 settled 就會先回到 pending 之後重新運行。

Promise 運作範例

接下來,來看看簡單的範例,藉此更了解上述各狀態的運行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function fn (n) {
return new Promise ((resolve, reject) => {
setTimeout(() => {
if (n) {
resolve('success')
} else {
reject(new Error('fail'))
}
}, 0)
})
}

fn (1)
.then((res) => {
console.log('successMessage:', res)
})
.catch((err) => {
console.log('errorMessage:', err)
})

這邊宣告了一個 fn 的 Promise 函式,透過 return 的方式回傳一個新的 Promise 物件,並傳入 resolvereject 兩個參數,幫助我們回傳成功與失敗的結果。

至於 setTimeout 就是一個很典型的非同步,所以範例才用 setTimeout 做說明。

自己建立 Promise

在了解 Promise 的運作概念後,來嘗試看看建立自定義的 Promise。

在建立 Promise 時候我們會透過 new Promise 來建立 Promise 的實體,但這邊要注意的是只寫 const a = new Promise 是不夠的,因為 new Promsie 會需要傳入一個 call back function 才能運作,所以要這樣寫 const a = new Promise(() => {}) 才是建立 Promise 的第一步喔!

接下來,來看看範例了解一下各狀態:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 如果先來看看剛剛宣告的 a,會發現它目前是 pending 的狀態
const a = new Promise(() => {})
console.log(a)

// 接著帶入我們前面提到的參數看看
const a = new Promise((resolve, rejcet) => {
resolve('success')
})

console.log(a) // 顯示狀態會變成 fulfilled,因為我們透過 resolve 回傳了結果。

a.then((res) => { // 透過 then 來接收 resolve 回傳的結果。
console.log(res) // success
})

// Promise 改加入參數 reject
const a = new Promise((resolve, rejcet) => {
reject('fail')
})

console.log(a) // 顯示狀態會變成 rejected,因為我們透過 reject 回傳了結果。

a.catch((err) => { // 透過 catch 來接收 rejcet 回傳的結果。
console.log(err)
})

看到這邊其實已經對 Promise 的建立有了基本的認知,但基本上 Promise 我們都會用函式的方式來建立一個 Promise 函式,而非像上面範例一樣宣告變數。

這邊稍微看一下陳述式與表達式建立 Promise 的起手式:

1
2
3
4
5
6
7
8
9
// 陳述式
function fn () {
return new Promise((resolve, reject) => {})
}

// 表達式
const fn2 = () => {
return new Promise((resolve, reject) => {})
}

接著 call back function 裡面的內容,我相信剛看完上面的講解,你應該是在熟悉不過了,我這邊就直接填入範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function fn (n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (n) {
resolve('success')
} else {
reject('fail')
}
}, 0)
})
}

fn (1)
.then((res) => {
console.log('success:', res)
})
.catch((err) => {
console.log('error:', err)
})

系列連結

Promise - 如何運用 Promise 處理非同步事件
Promise - Promise Chain
Promise - Promise 使用方法


參考資料

六角學院-JavaScript核心篇