- 原文地址:promisesaplus.com/
- Markdown 地址:github.com/Yangfan2016…
- 譯者:Yangfan2016
一個開放標準,對於開發人員可互操做的 JavaScript 承諾git
一個 promise 表明一個異步操做的最終結果。主要的操做方式是經過調用 promise 的 then
方法,它接受的回調函數接受 promise 成功的結果或失敗的緣由github
這個規範詳細的描述了 then
方法的行爲,提供一個互操做基礎,全部符合 Promises/A+ 的均可以依賴這個標準實現。所以,該規範已經十分穩定。儘管 Promises/A+ 組織可能會偶爾修改以實現向後兼容,咱們也會整合這些大的或不能向後兼容的改變,一塊兒研究,討論,測試。promise
曾經, Promises/A+ 解釋了早期 PromisesA 提議的條款,擴展了事實上的行爲和忽略了不標準和有問題的部分。異步
最終,Promises/A+ 規範並沒處理如何建立 fulfill,或 reject promise,而選擇了可互操做的 then
方法替代。在從此的工做中可能會考慮。函數
1.1 ‘promise’ 是一個有符合此標準的 then
方法的 object
或 function
測試
1.2 ‘thenable’ 是 then
方法定義的 object
或 function
this
1.3 ‘value’ 是一個 JavaScript 合法值(包括 undefined
,thenable,promise)code
1.4 ‘exception’ 是一個 throw
語句拋出錯誤的值對象
1.5 ‘reason’ 是一個代表 promise 失敗的緣由的值遞歸
一個 promise 有且只有一個狀態(pending,fulfilled,rejected 其中之一)
2.1.1 pending 狀態時:
2.1.2 fulfilled 狀態時:
2.1.2.1 不能再狀態爲任何其餘狀態
2.1.2.2 必須有一個 value,且不可改變
2.1.3 rejected 狀態時:
2.1.3.1 不能再狀態爲任何其餘狀態
2.1.3.2 必須有一個 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 是 fulfilled 狀態後調用,而且接受一個參數 value
2.2.2.2 它必定是在 promise 是 fulfilled 狀態後調用
2.2.2.3 它最多被調用一次
2.2.3 若是 onRejected 是一個函數:
2.2.3.1 它必定在 promise 是 rejected 狀態後調用,而且接受一個參數 reason
2.2.3.2 它必定在 promise 是 rejected 狀態後調用
2.2.3.3 它最多被調用一次
2.2.4 onFulfilled 或 onRejected 只在執行環境堆棧只包含平臺代碼以後調用 [3.1]
2.2.5 onFulfilled 和 onRejected 會做爲函數形式調用 (也就是說,默認 this
指向 global,嚴格模式 undefined
) [3.2]
2.2.6 在同一個 promise 實例中,then
能夠鏈式調用屢次
2.2.6.1 若是或當 promise 轉態是 fulfilled 時,全部的 onFulfilled 回調回以他們註冊時的順序依次執行
2.2.6.2 若是或當 promise 轉態是 rejected 時,全部的 onRejected 回調回以他們註冊時的順序依次執行
2.2.7 then 方法必定返回一個 promise
promise2 = promise1.then(onFulfilled, onRejected);
[[Resolve]](promise2, x)
處理解析
2.2.7.2 若是 onFulfilled 或 onRejected 裏拋出了一個異常,那麼 promise2 必須捕獲這個錯誤(接受一個 reason 參數)
2.2.7.3 若是 onFulfilled 不是一個函數,而且 promise1 狀態是 fulfilled,那麼 promise2 必定會接受到與 promse1 同樣的值 value
2.2.7.4 若是 onRejected 不是一個函數,而且 promise1 狀態是 rejected,promise2 必定會接受到與 promise1 同樣的值 reason
promise 處理程序是一個表現形式爲 [[Resolve]](promise, x) 的抽象處理操做。若是 x 是 thenable 類型,它會嘗試生成一個 promise 處理 x,不然它將直接 resolve x
只要 then 方法符合 Promises/A+ 規則,那麼對 thenables 處理就容許實現可互操做(鏈式調用,層層傳遞下去)。它也容許對那些不符合 Promises/A+ 的 then 方法進行 「吸取」
[[Resolve]](promise, x)
的執行表現形式以下步驟:
2.3.1 若是返回的 promise1 和 x 是指向同一個引用(循環引用),則拋出錯誤
2.3.2 若是 x 是一個 promise 實例,則採用它的狀態:
2.3.2.1 若是 x 是 pending 狀態,那麼保留它(遞歸執行這個 promise 處理程序),直到 pending 狀態轉爲 fulfilled 或 rejected 狀態
2.3.2.2 若是或當 x 狀態是 fulfilled,resolve 它,而且傳入和 promise1 同樣的值 value
2.3.2.3 若是或當 x 狀態是 rejected,reject 它,而且傳入和 promise1 同樣的值 reason
2.3.3 此外,若是 x 是個對象或函數類型
2.3.3.1 把 x.then
賦值給 then
變量
2.3.3.2 若是捕獲(try
,catch
)到 x.then
拋出的錯誤的話,須要 reject 這個promise
2.3.3.3 若是 then
是函數類型,那個用 x 調用它(將 then
的 this
指向 x),第一個參數傳 resolvePromise ,第二個參數傳 rejectPromise:
2.3.3.3.1 若是或當 resolvePromise 被調用並接受一個參數 y 時,執行 [[Resolve]](promise, y)
2.3.3.3.2 若是或當 rejectPromise 被調用並接受一個參數 r 時,執行 reject(r)
2.3.3.3.3 若是 resolvePromise 和 rejectPromise 已經被調用或以相同的參數屢次調用的話嗎,優先第一次的調用,而且以後的調用所有被忽略(避免屢次調用)
2.3.3.4 若是 then
執行過程當中拋出了異常,
2.3.3.3.4.1 若是 resolvePromise 或 rejectPromise 已經被調用,那麼忽略異常
2.3.3.3.4.2 不然,則 reject 這個異常
2.3.3.4 若是 then
不是函數類型,直接 resolve x(resolve(x))
2.3.4 若是 x 即不是函數類型也不是對象類型,直接 resolve x(resolve(x))
若是被 resolve 的 promise 參與了 thenable 的循環鏈中,那麼可能會致使無限遞歸。咱們鼓勵實現檢測這種無限遞歸的方法而且返回一個錯誤信息,但並非必須的 [3.6]
3.1 這裏的 「平臺代碼」是指引擎,環境,和 promise 實現代碼。實際上,這個要求確保 onFulfilled 和 onRejected 都在下一輪的事件循環中(一個新的棧)被異步調用。能夠用宏任務,例如:setTimeout
,setImmediate
或者微任務,例如:MutationObsever
或 process.nextTick
實現。 因爲 promise 的實現被當作平臺代碼,因此它自己可能包含一個任務隊列或 「trampoline」 的處理程序
3.2 這個 this
在嚴格模式下是 undefined
,在寬鬆模式,指向 global 對象
3.3 具體的實現能夠容許 promise2 和 promise1 絕對相等,要知足全部要求。每個處理 promise2 和 promise1 絕對相等的實現都要寫上文檔標註
3.4 一般,只有它來自當前實現才能夠判斷 x 是一個真正的 promise。 此條款容許採起已知符合 promise 標準實現的狀態
3.5 把 x.then
存起來,而後測試、調用這個引用,避免屢次訪問 x.then
屬性。這麼作的緣由是防止每次獲取 x.then
時,返回不一樣的狀況(ES5
的 getter
特性可能會產生反作用)
3.6 實現不該該武斷地限制 thenable 鏈的深度,假設超出限制的無限遞歸。只有真正的循環引用纔會致使一個 TypeError
錯誤,若是遇到一個不一樣的無限遞歸 thenable 鏈,一直遞歸永遠是正確的行爲
- 本文僅表明原做者我的觀點,譯者不發表任何觀點
- Markdown 文件由譯者手動整理,若有勘誤,歡迎指正
- 譯文和原文采用同樣協議,侵刪