0%

Promise (I) - state 和 result 的改變

本文開始

本文是跟著這一篇文章的教學內容所寫下的紀錄。

假設你是一個歌手,你的 fans 沒日沒夜的跟你要你將要發行的新歌。
接著,你給這些 fans 一個表單,讓他們填入他們的 email address,一旦新歌發布了,所有在 list 紹的 email address 的人都會收到通知,即使在作曲的過程中發生一些非常不順利的結果,例如:工作室失火,這些訂閱你的 fans 們,也一樣會收到通知。

這樣子的操作,讓你不再被 fans 煩,而這些 fans 也能即時的收到新歌分布的消息。

我們可以將以上這種狀況類推到 JS 的 Promise 的運作機制

Promise 是 JS 的一種特別的物件。
它可以用來連結 索取資源部分的程式碼在取得資源後,在利用這個資源做其他事的程式碼 這兩部分的功能。
以下程式碼是用來建構 Promise 物件的寫法

1
2
3
let promise = new Promise(function(resolve, reject) {
// executor
});

傳入 new Promise 的函式叫做 executor。
當 new Promise 被執行後,executor 內部的內容就會被執行。

executor function 執行結果

這個 executor function 有兩個參數,分別為 resolvereject
以上這兩個參數皆為 callback function 並且為 JS 的內建函式。

當 executor function 有執行結果時,會依照不同結果而去呼叫不一樣的 callback function
.呼叫 resolve(value) - 如果 executor function 執行成功並夾帶著執行結果 value

.呼叫 reject(error) - 如果 executor function 執行失敗並夾帶著 error 物件

簡單來說, executor function 執行成功呼叫 resolve,若執行失敗呼叫 reject

Promise 物件的成員屬性

以下是 Promise 物件含有的成員屬性

state: 初始值為 pending,若 resolve 被呼叫則會變成 fulfilled,若 reject 被呼叫則會變成 rejected

result: 初始值為 undefined ,若 resolve(value) 被呼叫則會變成 value(也就是回傳的結果),若 reject(error) 被呼叫則會變成 error

下圖即為上述成員屬性,因呼叫不同的 callback function 而改變的流程

這邊舉個小範例

1
2
3
new Promise(function(resolve, reject) {
setTimeout(() => {resolve('success')}, 2000)
})

上面的範例, new Promise 是一個表達式所以它會直接執行該 Promise 物件裡面的內容,可以看到以上的範例中定義的 executor function 利用 setTimeout function 在 2 秒後才呼叫 resolve function,並夾帶 value success。

所以,上面範例的 Promise 物件的成員屬性改變的過程如下

那我們改寫一下上面的範例,改成呼叫 reject 並回傳 error 物件

1
2
3
4
5
new Promise(function(resolve, reject) {
setTimeout(() => {
reject(new Error('error'))
}, 2000)
})

上面範例的 Promise 物件的成員屬性改變的過程如下

Note:
稍微提一下,reject 回傳的結果不一定一定要是 Error 物件喔,你也可以單純傳數字或者字串等等的內容,以上面的範例改寫的話,會長這樣
reject(‘fail’) ,如此一來就只會回傳字串內容 ‘fail’

❗executor function 只會執行一個 resolvereject

如果今天我們在 executor function 裡面放入多個 resolve 或者 reject 會發生什麼事呢?

1
2
3
4
5
new Promise(function(resolve, reject){
resolve('first success');
reject(new Error('failed')); // ignored
setTimeout(() => { resolve('second success');}, 0); // ignored
})

以上的範例只有第一個 resolve 會被執行到優,後面的都會被忽略。
另外, resolvereject 都只接受一個參數而已,如果,你再多加其他的參數進去 resolvereject 裡,是不會被理會的。

❗可以立即呼叫 resolvereject

通常專案中我們會利用 Promise 去執行非同步的任務 (e.g. 跟 server 索取資料 …),這個非同步任務通常會經過一段時間後,才呼叫 resolvereject

但我們其實也可以立即呼叫 resolvereject ,像下面範例這樣。

1
2
3
new Promise(function(resolve, reject) => {
resolve('immediately call');
})

上面的範例,就會立即呼叫 resolve function 喔。

stateresult 是內建的 Promise 成員屬性

stateresult 是內建的 Promise 成員屬性,我們無法直接調用這兩個成員屬性值,
但 Promise 物件還是有開放像是 then, catch, finally 這三個成員函式讓我們使用。

Conclusion

以上的內容,先記錄了
Promise 物件可以怎麼被創建
Promise 物件的 executor function 可以寫入什麼內容,以及它的參數 resolvereject 這兩個 callback function。
Promise 物件的成員屬性 stateresult 會在呼叫 resolvereject 之後,被修改成相對應的改變。

Reference

  1. https://javascript.info/promise-basics