Promise的概念在ES6標準推出來以前已經深刻人心,不少框架和第三方庫都有相似的實現。但在深刻理解ES6的Promise對象的時候,受以前經驗的影響,不少概念給人似是而非的感受,其中有一個特別明顯的地方就是ES6中對Promise對象狀態的定義以及resolved概念。
html
Promise對象有三個狀態:pending,fulfilled,rejected,MDN文檔上對Promise對象狀態變化過程用一幅圖描述:前端
圖中有幾個小細節:git
fulfilled
,rejected
狀態前promise都處在pending
狀態。settled
包括了fulfilled
和rejected
。pending
,fulfilled
,rejected
三種狀態下切換。事情在如今看來都很美好,狀態清晰,一目瞭然。然而,在各類教程中咱們會看到這樣一個狀態:resolved
,阮老師的ECMAScript 6 入門中直接把它看成了fulfilled
狀態:es6
Promise對象表明一個異步操做,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和Rejected(已失敗)。github
可是MDN中的備註是這樣寫的:promise
你可能也會聽到一個術語
resolved
,它表示Promise對象處於settled
狀態,或者Promise對象被鎖定在了調用鏈中。app
嗯?記不記得上面提到settled
狀態包括fulfilled
和rejected
狀態,那麼他至少不能和fulfilled
狀態劃等號吧?因而我又搜了搜,發現網上不少文章提到resolved
這個詞時,有人直接看成fulfilled
狀態,有人把它理解爲complete
(相似地,fulfilled
是success,rejected
天然就是error或者failure),不過更多人都是很含糊地引用了一下文檔或者阮老師的文章。框架
不過確實有人直接提出了這個問題:Promise的fulfill和resolve爲啥要用兩個詞?,我着重看了賀師俊老師的回答:dom
由於 fulfill 和 resolve 是不一樣的。
resolve 只是表示這個 promise 已經肯定了,好比 promise A 被 resolve 爲 promise B,則 A 已經 resolved 可是並未 fulfilled 。異步
好吧,我認可我一開始看沒看懂...
不過還好在備註那裏MDN放出了一篇幫助理解的文章,Domenic Denicola 的 States and Fates,基本把這兩個概念說清楚了,不過文中只有簡單的文字描述,下面說一下我本身的理解。
文章將Promise分得更細,分爲了狀態(state)和結果(fates,命運,原諒我粗淺的翻譯)。
狀態(state)就是上面提到的三種狀態,須要稍微留意一下的是,文中提到settled
不是一種Promise狀態,只是一種語義上的便利,說白了就是描述Promise肯定了而已。
結果(fates)分爲resolved
和unresolved
,兩種結果互斥。
resolved,原文解釋有點繞:
A promise is resolved if trying to resolve or reject it has no effect,當沒辦法去resolve或reject一個promise的時候,這個promise就是resolved的。
unresolved,原文解釋卻是很簡單:非resolved的promise...... (:з」∠)
顯而易見,只要理解了resolved
的描述,天然就理解unresolved
。首先先提一個Promise的概念,即當Promise的狀態一旦改變,就永久保持該狀態。因此何時沒辦法去resolve或reject一個promise對象呢?
fulfilled
和rejected
狀態的promise對象,由於他們已經沒法改變狀態,而resolve和reject只能對pending
狀態的promise有效。pending
狀態的promise對象也有可能處於resolved
,當promise對象被'鎖定'在另一個promise對象或者一個非即時返回的thenable
函數中時,也就是上面賀老師提到的promise A 被 resolve 爲 promise B這種狀況,爲了幫助理解,下面用代碼舉個例子。說明:Chrome(57.0.2987.133)打印promise對象的時候,[[PromiseStatus]]
有三個值:pending,resolved,rejected,這裏的resolved
狀態就是指fulfilled
狀態,和咱們要說明的resolved
沒有關係,在firefox(49.0.1)中,[[PromiseStatus]]
三個值和標準相同:pending,fulfilled,rejected。爲了不混淆,用firefox作測試
先上一個簡單的代碼:
var p1 = new Promise((resolve, reject) => { setTimeout(resolve, 1000, 'p1 resolve'); }); p1.then(value => { console.log(value); // p1 resolve console.log(p1); // Promise { <state>: "fulfilled", <value>: "p1 resolve" } })
很簡單,一秒後打印p1 resolve,p1對象狀態爲fulfilled
。再來看第二例子,在resolve方法中新建了一個Promise對象:
var p1 = new Promise((resolve, reject) => { function F() { resolve(new Promise((resolve, reject) => { console.log(p1); // Promise { <state>: "pending" } setTimeout(resolve, 2000, 'new Promise resolve'); })) } setTimeout(F, 1000, 'p1 resolve'); }); p1.then(function(value) { console.log(value); // new Promise resolve console.log(p1); // Promise { <state>: "fulfilled", <value>: "new Promise resolve" } })
運行一下發現,一秒後打印
Promise { <state>: "pending" }
三秒後打印
new Promise resolve Promise { <state>: "fulfilled", <value>: "new Promise resolve" }
能夠看到,一秒後p1調用了resolve方法,和上一個例子同樣被resolve了,理應變爲fulfilled
狀態,可是他被'鎖定'在了一個新的Promise對象中,因此狀態沒有馬上改變並執行onfulfilled
方法,而是依然處於pending
狀態,可是很明顯的是,他的最終結果(這裏能夠體會到稱爲fate的緣由,有種宿命的味道)就是fulfilled
狀態,此時的p1不能再resolve或reject。再過了兩秒後新Promise對象resolve,p1執行then(),狀態變爲fulfilled
,打印的值也變成了new Promise resolve,而不是p1 resolve。此時打印出的p1的狀態就是fulfilled。
到此,處於pending
狀態的promise對象也有可能處於resolved
狀況就很清楚了,至於unresolved,就是promise能夠被resolve或reject的時候,此時promise對象必定處於pending
狀態且沒有被resolve或reject爲其餘Promise對象 / 非即時返回的thenable
函數。而反過來,處於pending
狀態的promise對象不必定是unresolved。
到這裏Promise對象的狀態和resolved的概念差很少都清楚了,這篇文章也是我我的理解過程的一個記錄。不過參考到的文章很少,文中的解釋可能並非很準確,因此在這裏貼出來,但願能看看其餘人的理解。
提及來,這篇文章離我上一篇文章已經好久了,真是光陰似箭,歲月......算了,仍是不感慨了。如今工做確實沒有在學校那會兒充足的時間和精力,總結仍是有很多,大部分都在我的的筆記裏,沒有貼到博客。有些以爲總結分量不夠,有些以爲我的的理解不深,不敢隨意貼出來。不過在學習一些稍微深刻一點的概念的時候,總以爲網上的一些資料並非很全面和客觀,人云亦云的東西太多,本身的理解也是七七八八。因此但願可以貼出來和你們交流,防止本身閉門造車,後續若是工做時間容許,會發一些這樣的文章,對前端一些比較重要的知識點深刻理解。
本文來源:JuFoFu
本文地址:http://www.cnblogs.com/JuFoFu/p/5140302.html
Domenic Denicola . States and Fates
阮一峯 . Promise 對象
MDN . Promise