徹底理解PromiseA+規範

語言: CN / TW / HK

theme: channing-cyan highlight: night-owl


這是我參與11月更文挑戰的第14天,活動詳情檢視:[2021最後一次更文挑戰](https://juejin.cn/post/7023643374569816095/ "https://juejin.cn/post/7023643374569816095/") > TIP 👉 **著意栽花花不發,等閒插柳柳成陰。元·關漢卿《包待制智斬魯齋郎**

前言

Web Component是前端界一直非常熱衷的一個領域,用第三方元件化的框架去實現的話,你需要依賴框架本身很多東西,很多時候我們只是簡單的幾個元件,不是很大,也不是很多,所以為了保證元件的`輕量,簡單`,其實這個時候我們並不想採用第三方的框架。 # PromiseA+規範 講解PromiseA+規範前, 咱們先來了解一下這些術語, 以便在後續提到的時候有明確且統一的概念. ## 術語 1. promise 是一個有then方法的物件或者是函式,行為遵循本規範 2. thenable 是一個有then方法的物件或者是函式 3. value 是promise狀態成功時的值,也就是resolve的引數, 包括各種資料型別, 也包括undefined/thenable或者是 promise 4. reason 是promise狀態失敗時的值, 也就是reject的引數, 表示拒絕的原因 5. exception 是一個使用throw丟擲的異常值 ## 規範 接下來分幾部分來講解PromiseA+規範. ### Promise States promise應該有三種狀態. 要注意他們之間的流轉關係. 1. pending 1.1 初始的狀態, 可改變. 1.2 一個promise在resolve或者reject前都處於這個狀態。 1.3 可以通過 resolve -> fulfilled 狀態; 1.4 可以通過 reject -> rejected 狀態; 2. fulfilled 2.1 最終態, 不可變. 2.2 一個promise被resolve後會變成這個狀態. 2.3 必須擁有一個value值 3. rejected 3.1 最終態, 不可變. 3.2 一個promise被reject後會變成這個狀態 3.3 必須擁有一個reason Tips: 總結一下, 就是promise的狀態流轉是這樣的 pending -> resolve(value) -> fulfilled pending -> reject(reason) -> rejected ### then promise應該提供一個then方法, 用來訪問最終的結果, 無論是value還是reason. ```js promise.then(onFulfilled, onRejected) ``` 1. 引數要求 1.1 onFulfilled 必須是函式型別, 如果不是函式, 應該被忽略. 1.2 onRejected 必須是函式型別, 如果不是函式, 應該被忽略. 2. onFulfilled 特性 2.1 在promise變成 fulfilled 時,應該呼叫 onFulfilled, 引數是value 2.2 在promise變成 fulfilled 之前, 不應該被呼叫. 2.3 只能被呼叫一次(所以在實現的時候需要一個變數來限制執行次數) 3. onRejected 特性 3.1 在promise變成 rejected 時,應該呼叫 onRejected, 引數是reason 3.2 在promise變成 rejected 之前, 不應該被呼叫. 3.3 只能被呼叫一次(所以在實現的時候需要一個變數來限制執行次數) 4. onFulfilled 和 onRejected 應該是微任務 這裡用queueMicrotask來實現微任務的呼叫. 5. then方法可以被呼叫多次 5.1 promise狀態變成 fulfilled 後,所有的 onFulfilled 回撥都需要按照then的順序執行, 也就是按照註冊順序執行(所以在實現的時候需要一個數組來存放多個onFulfilled的回撥) 5.2 promise狀態變成 rejected 後,所有的 onRejected 回撥都需要按照then的順序執行, 也就是按照註冊順序執行(所以在實現的時候需要一個數組來存放多個onRejected的回撥) 6. 返回值 then 應該返回一個promise ```js promise2 = promise1.then(onFulfilled, onRejected); ``` 6.1 onFulfilled 或 onRejected 執行的結果為x, 呼叫 resolvePromise( 這裡大家可能難以理解, 可以先保留疑問, 下面詳細講一下resolvePromise是什麼東西 ) 6.2 如果 onFulfilled 或者 onRejected 執行時丟擲異常e, promise2需要被reject 6.3 如果 onFulfilled 不是一個函式, promise2 以promise1的value 觸發fulfilled 6.4 如果 onRejected 不是一個函式, promise2 以promise1的reason 觸發rejected 7. resolvePromise ```js resolvePromise(promise2, x, resolve, reject) ``` 7.1 如果 promise2 和 x 相等,那麼 reject TypeError 7.2 如果 x 是一個 promsie 如果x是pending態,那麼promise必須要在pending,直到 x 變成 fulfilled or rejected. 如果 x 被 fulfilled, fulfill promise with the same value. 如果 x 被 rejected, reject promise with the same reason. 7.3 如果 x 是一個 object 或者 是一個 function let then = x.then. 如果 x.then 這步出錯,那麼 reject promise with e as the reason. 如果 then 是一個函式,then.call(x, resolvePromiseFn, rejectPromise) resolvePromiseFn 的 入參是 y, 執行 resolvePromise(promise2, y, resolve, reject); rejectPromise 的 入參是 r, reject promise with r. 如果 resolvePromise 和 rejectPromise 都呼叫了,那麼第一個呼叫優先,後面的呼叫忽略。 如果呼叫then丟擲異常e 如果 resolvePromise 或 rejectPromise 已經被呼叫,那麼忽略 則,reject promise with e as the reason 如果 then 不是一個function. fulfill promise with x. 這段描述看起來非常的空洞乏味, 最重要的是看不懂! 所以待會實現程式碼的時候, 同學們注意一下resolvePromise函式具體的實現, 結合程式碼來看會好很多. 樣式這塊就先不放了 「歡迎在評論區討論」 #### 希望看完的朋友可以給個贊,鼓勵一下