俗話說好記性不如爛筆頭,因此我決定翻譯一下Promise/A+
規範,幫助本身更加深入的理解promise
,爲以後手擼promise
源碼作準備,同時也但願本篇文章對你們也有所幫助。前端
這是一個實現者爲實施者提供的開源的、可互操做的JavaScript Promise規範git
promise
表明一個異步操做的最終結果。與promise
的主要互動方式是經過then
方法註冊回調函數來接收promise
的最終值或者promise
未完成的緣由。github
該規範詳細描述了then
方法的行爲,它提供了一個可互操做的基礎,全部Promises/A +
符合 promise
的實現均可以依賴於這個基礎。所以,該規範被認爲是很是穩定的。儘管Promises/A+
的做者可能偶爾會修改規範,對其進行一些向後兼容的小修改,以解決新發現的問題,咱們只有在仔細考慮、討論和測試後,纔會集成大型或者不向後兼容的變動。web
歷史上,Promises/A+
澄清了早期的Promises/A proposal的行爲條款,將其拓展到涵蓋事實的行爲,而且省略了未指定或有問題的部分。算法
最後,Promises/A+
規範的核心不是處理如何建立、完成或者失敗的promises
,而是選擇專一於一個可互操做的then
方法。將來在配套規範中的工做可能會涉及這些主題。promise
1.1 promise
是具備then
方法的對象或者函數,其行爲符合規範。app
1.2 thenable
是定義在then
方法上的對象或者函數。異步
1.3 value
是任何合法的JavaScript
值(包括undefined
,thenable
,或者promise
)函數
1.4 exception
是使用拋出語句拋出的值學習
1.5 reason
是一個代表promise
爲何失敗的值
2.1.1 當promise
狀態爲pending
時:
2.1.2 當promise
狀態爲fulfilled
時:
2.1.2.1 不能變爲任何一種狀態
2.1.2.2 必須有一個value
,這個value
不能改變
2.1.3 當promise
爲rejected
時:
2.1.3.1 不能變爲任何一種狀態
2.1.3.2 必須有一個reason
,這個reason
不能改變
promise
必須提供一個then
方法,來訪問它當前或最終的value
或reason
。
一個promise
的then
方法接收兩個參數:
promise.then(onFulfilled, onRejected)
複製代碼
2.2.1 onFulfilled
和onRejected
都是可選的參數
2.2.1.1 若是onFulfilled
不是函數,必須被忽略
2.2.1.2 若是onRejected
不是函數,必須被忽略
2.2.2 若是onFulfilled
是一個函數
2.2.2.1 它必須在promise
完成後被調用,而後把promise
的值做爲它的第一個參數
2.2.2.2 它不能在promise
完成前被調用。
2.2.2.3 它不能被調用超過一次。
2.2.3 若是onRejected
是一個函數
2.2.3.1 它必須在promise
失敗後被調用,而後把promise
的值做爲它的第一個參數
2.2.3.2 它不能在promise
失敗前被調用。
2.2.3.3 它不能被調用超過一次。
2.2.4 在執行上下文堆棧(execution context)僅包含平臺代碼以前,不得調用 onFulfilled
和onRejected
[3.1]
2.2.5 onFulfilled
和onRejected
必須做爲函數調用(即沒有this
值)[3.2]
2.2.6 then
方法可能在同一次promise
中被調用屢次
2.2.6.1 若是/當promise
完成時,全部相應的onFulfilled
回調必須按照最原始的then
順序來執行
2.2.6.2 若是/當promise
失敗時,全部相應的onRejected
回調必須按照最原始的then
順序來執行
2.2.7 then
方法必須返回一個promise
promise2 = promise1.then(onFulfilled, onRejected);
2.2.7.1 若是onFulfilled
和onRejected
返回一個值x
,請運行Promise Resolution Procedure [[Resolve]](promise2, x)
2.2.7.2 若是onFulfilled
和onRejected
拋出一個異常e
,promise2
必須拒絕並將e
做爲reason
2.2.7.3 若是onFulfilled
不是一個函數,且promise1
爲完成狀態,promise2
必須使用與promise1
相同的value
完成
2.2.7.4 若是onRejected
不是一個函數,且promise1
爲失敗狀態,promise2
必須使用與promise1
相同的reason
完成
promise
解析過程是一個以輸入promise
和value
的抽象操做,咱們記做[[Resolve]](promise, x)
,若是x
是thenable
,假設x
的行爲有點像promise
,它會嘗試讓promise
採用x
的狀態。不然,它將使用x
值來完成promise
。
只要有實現Promises/A+
兼容的then
方法,對thenable
的處理容許使用promise
實現可以互操做。它還容許Promises/A+
實現使用合理的then
方法「同化」不一致的實現。
運行[[Resolve]](promise, x)
,執行如下的步驟:
2.3.1 若是promise
和x
引用同一個對象,則用TypeError
做爲reason
拒絕promise
2.3.2 若是x
是一個promise
,則採用它的狀態[3.4]
2.3.2.1 若是x
爲pending
狀態,promise
必須保持pending
狀態直到x
成功或者失敗
2.3.2.2 若是x
爲完成狀態,用相同的值完成promise
2.3.2.3 若是x
爲失敗狀態,用相同的reason
拒絕promise
2.3.3 若是x
是一個對象或函數
2.3.3.1 讓then
爲x.then
[3.5]
2.3.3.2 若是檢索屬性x.then
的結果拋出一個異常e
,用e
做爲reason
拒絕promise
2.3.3.3 若是then
是一個函數,把x
做爲this
調用它,第一個參數resolvePromise
和第二個參數rejectPromise
,其中:
2.3.3.3.1 若是resolvePromise
被y
值調用,運行[[Resolve]](promise, y)
2.3.3.3.2 若是rejectPromise
被爲r
的reason
調用,用r
來拒絕promise
2.3.3.3.3 若是 resolvePromise
和rejectPromise
都被調用,或者對同一個參數進行屢次調用,則第一次調用優先,任何進一步的調用被忽略
2.3.3.4 若是then
不是函數,用x
來完成promise
2.3.4 若是x
不是對象或者函數,用x
來完成promise
若是使用參與循環的可循環鏈的可轉換組件解決了一個promise
,這樣,[[Resolve]](promise, thenable)
的遞歸性質致使了再次調用[[Resolve]](promise, thenable)
,遵循上述算法將致使無限遞歸。鼓勵(但不是必須)實現來檢測這種遞歸且用包含信息的TypeError
做爲reason
拒絕promise
。[3.6]
這裏的「平臺代碼」是指引擎,環境和promise
實現代碼。在實踐中,這個需求確保onFulfilled
和onRejected
異步執行,在事件循環以後調用then
,而且使用一個新棧。這能夠經過setTimeout
或者setImmediate
宏任務機制,或者使用MutationObserver
或者process.nextTick
微任務機制來實現。因爲promise
實現被視爲平臺代碼,所以它自己可能包含一個任務調度隊列或「蹦牀」在其中調用處理程序。
也就是說,在嚴格模式下,this
爲undefined
,在寬鬆模式中,它是一個全局對象(global object
)
在知足全部需求的狀況下,能夠容許實現promise2 === promise1
,每一個實現都應該記錄它是否可以產生promise2 === promise1
以及在何種條件下產生
一般,只有x
來自於當前實例時,才知道它是一個真正的promise
,此條款容許使用特定的實現方法來採用已知符合promise
的狀態。
這個過程首先存儲對x.then
的引用,而後測試,而後調用這個引用。避免了對x.then
屬性的屢次訪問。這些預防措施對於確保訪問者屬性的一致性很是重要,由於訪問者屬性的值可能在兩次檢索之間發生變化。
實現不該該對thenable
鏈的深度設置任何限制,並假設遞歸超出限制。只有真正的循環纔會致使TypeError
,若是遇到無窮多個thenable
鏈,那麼永遠遞歸是正確的行爲。
熟悉promise
規範有助於咱們深入理解promise
原理,爲以後看源碼,手寫源碼鋪路~好久不碰英語了,很長時間以後第一次作翻譯,若是有翻譯很差的地方,還但願指出~咱們共同窗習,共同進步~
最後,分享一下個人公衆號「web前端日記」,若是想更加及時的看見文章,立刻就去關注哇😍