Promise 筆記
介紹
Promises/A+標準定義
所謂的Promises/A+標準,其實就是個幾千字的一頁網頁而已,裡面的說明與用語並不會太難理解。雖然ES6標準中也有自己的Promise物件標準章節,但因為裡面涉及很多實作技術說明,明顯地用字遣詞艱澀許多,所以在這裡就不多加討論。以下使用Promises/A+標準作為一個開始,來解說Promise的標準裡有什麼內容。
專門用語
- promise (承諾)是一個帶有遵照這個規格的then方法的物件
- thenable 是一個有定義then方法的物件
- value 合法的JavaScript值(包含undefined、thenable與promise)
- exception (例外)使用throw語句丟出來的值
- reason (理由)是表明為什麼promise被拒絕(rejected)的值
註: 另外有個常見的專有名詞 settled(固定的) 一個promise最後的狀態,也就是fulfilled(已實現)或rejected(已拒絕)
註: reason(理由)通常是一個Error物件,用於錯誤處理。
註: promise/帕咪死/ 的中文翻譯是”承諾”、”約定”,本書中並不會用它的中文翻譯字詞,都是直接用英文。
Promise狀態
promise物件必定是以下三種狀態中的其中一種: pending(等待中)、fulfilled(已實現)或rejected(已拒絕)。
2.1.1 當處在pending(等待中)時,一個promise:
2.1.1.1 可能會轉變到不是fulfilled(已實現)就是rejected(已拒絕)狀態
2.2.1 當處在fulfilled(已實現)時,一個promise:
2.2.1.1 必定不會再轉變到其他任何狀態
2.2.1.2 必定有不能再更動的值
2.3.1 當處在rejected(已拒絕)時,一個promise:
2.3.1.1 必定不會再轉變到其他任何狀態
2.3.1.2 必定有不能再更動的值reason(理由)
這個用下面的圖解說明,應該可以很清楚的理解:
狀態是在Promise結構很重要的一個屬性,因為promise物件一開始都是代表懸而未決的值,所以一開始在promise物件在建立時,狀態都是pending(等待中),之後可以轉變到fulfilled(已實現)就是rejected(已拒絕)其中一個,然後就固定不變了。如果有產生value(值)的情況就是轉變到fulfilled(已實現)狀態,而如果是有reason(理由)時,代表要轉變到rejected(已拒絕)狀態。
建立一個 Promise
看完上面的比喻讓我們對應到 Javascript。
1 | var isMomHappy = false |
第一行我們使用一個 Boolean isMomHappy 定義媽媽是否開心。
我們宣告一個 Promise _willIGetNewPhone_。這個 Promise 可能是被 履行(resolved) 又或者 _拒絕(rejected)_。
Promise 標準的語法可以參考 MDN
new Promise(function (resolve, reject) {})
我們需要記得的是如果一個 Promise 執行成功要在內部 function 呼叫 resolve(成功結果) ,如果結果是失敗則呼叫 reject(失敗結果) 。在我們的範例中如果媽媽開心,我們將得到手機因此我們執行 _reslove(phone)_,如果媽媽不高興則執行 _reject(reason)_。
使用 Promise
到這一步我們已經有了一個 Promise,讓我們接著來使用它。
1 | var askMom = function () { |
- 首先我們有個 function 叫 askMom 在這個 function 中,我們將利用 Promise willIGetNewPhone。
- 我們希望一旦等待的結果發生時可以採取對應的動作,我們可以使用 .then 或 .catch 來執行對應的行為。
- 在這個範例中,我們在 .then 中使用 function (fulfilled){},而這個 fulfilled 就是從 Promise 的 resolve(成功結果) 傳來的結果,範例中這個結果就是 phone 物件。
- 在 .catch 中我們使用了 function (error) {}。而這個 error 就是從 Promise 的 reject(失敗結果) 傳來的即 reason。
鏈式調用 Promise
假如你承諾您的朋友,如果你拿到新手機會借他們看看。這又是另一個 Promise。讓我們繼續來撰寫這個範例:
1 | var showOff = function (phone) { |
- 在這個範例,您可能發現到我們根本沒有呼叫 reject,這是可選的,我們可以省略不調用。
- 另外,我們可以透過使用 Promise.resolve 簡化這個範例。
1 | var showOff = function (phone) { |
接著讓我們來看看如何串連 Promise。在 willIGetNewPhone 這個 Promise 之後接續 showOff Promise。
1 | var askMom = function () { |
這就是 Promise 串連的方式。
非同步
Promise 是非同步的,讓我們在呼叫 Promise 的前後加上 console.log
1 | var askMom = function () { |
順序是
1 | 1. before asking Mom |
ES5, ES6/ES2015,ES7/Next 的 Promise
完整範例
1 | const isMomHappy = true |