如今不少大廠面試前端都會要求可以手動的寫出一個Promise
,因此這裏整理了一份手寫的Promise
。前端
絕對詳細,功能絕對強大。若是你不瞭解Promise
的基本使用,那麼本篇文章可能不太適合你,若是你對Promise
有過一些瞭解,那麼這篇文章絕對是你進階的好幫手。面試
除開catch()
以及finally()
和allSettled
接口沒實現以外,其餘的全部原生Promise
支持的功能此手寫的Promise
都支持。數組
書寫Promise
的難度其實就在於then()
方法的鏈式調用以及值穿透傳遞,其餘的其實都還好。promise
讓這篇文章滾進你的收藏夾吧!異步
在原生Promise
中具備三種狀態,分別是函數
pending
:未解決狀態優化
fulfilled
:已解決狀態this
rejected
:解決失敗狀態線程
因此第一步,要先實現這三種狀態。code
而且在原生Promise
中具備value
用於記錄resolve()
與reject()
中的值用於傳遞給then()
方法。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始爲準備狀態 this.value = null; // 初始值 } }
原生Promise
的構造函數中會接收一個executor
參數,該參數當是一個函數。
用於同步的執行當前任務,當任務完成後應該具備resolve()
方法以及reject()
方法來通知then()
方法當前執行任務的執行狀態並傳遞值。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 executor(this.resolve, this.reject); // 傳遞形參,運行executor函數 } resolve(value) { this.status = MyPromise.FUFILLED; this.value = value; } reject(reason) { this.status = MyPromise.REJECTED; this.value = reason; } }
上面這樣寫在執行resolve()
以及reject()
時會出現問題,緣由是this
指向爲undefiled
(嚴格模式)。
<script src="./Promise核心.js"></script> <script> "use strict"; let p1 = new MyPromise((resolve, reject) => { resolve("成功") }) console.log(p1); </script>
這是因爲咱們在執行函數中調用了resolve()
與reject()
,故this
指向爲executor
的函數上下文。
解決這個問題可使用bind()
來改變this
指向。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } resolve(value) { this.status = MyPromise.FUFILLED; this.value = value; } reject(reason) { this.status = MyPromise.REJECTED; this.value = reason; } }
當前Promise
狀態只應該改變一次而不能屢次改變,顯然咱們上面的代碼不能作到這點限制。
<script src="./Promise核心.js"></script> <script> "use strict"; let p1 = new MyPromise((resolve, reject) => { resolve("成功"); reject("失敗"); // 對於原生Promise來講,狀態只能改變一次。可是這裏卻容許兩次改變,故是有問題的 }) console.log(p1); // MyPromise {status: "rejected", value: "失敗"} </script>
因此這裏要對代碼加上限制。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; } } }
在執行函數executor
中可能引起異常,這會讓當前的Promise
的狀態改變爲rejected
。
因此在上面代碼基礎上須要加入try...catch
進行處理。
當then()
方法捕捉到執行函數executor
中的異常時,可讓第二個參數的函數對其異常進行處理,可是咱們目前還沒實現then()
,因此直接丟給reject()
便可,當實現then()
時天然會使用到reject()
中傳遞過來的值。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; } } }
原生的Promise
狀態改變後,能夠執行其下的then()
方法,因此咱們須要來封裝出一個then()
方法。
then()
方法接收兩個函數,第一個函數onFulfilled
用於處理上一個Promise
的fulfilled
狀態,第二個函數onRejected
用於處理上一個Promise
的rejected
狀態。
而且then()
方法中的這兩個函數都應該具備一個形參,用於接收到Promise
的resolve()
或reject()
中傳遞的值。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; } } then(onFulfilled, onRejected) { if(this.status == MyPromise.FUFILLED){ // 狀態改變時執行 onFulfilled(this.value); } if(this.status == MyPromise.REJECTED){ // 狀態改變時執行 onRejected(this.value); } } }
上面已經說過,then()
方法具備兩個參數,這兩個參數分別對應兩個函數用來處理上一個Promsie
的resolve()
與reject()
。
可是在原生Promise
中,這兩個方法能夠不進行傳遞,因此咱們須要對上述代碼進行優化。
當then()
方法中的某一個參數不爲函數時,讓它自動建立一個空函數。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; } } then(onFulfilled, onRejected) { if(typeof onFulfilled != "function"){ // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = ()=>{}; } if(typeof onRejected != "function"){ // 若是傳入的不是一個函數,默認建立空函數 onRejected = ()=>{}; } if(this.status == MyPromise.FUFILLED){ // 狀態改變時執行 onFulfilled(this.value); } if(this.status == MyPromise.REJECTED){ // 狀態改變時執行 onRejected(this.value); } } }
當then()
方法中處理fulfilled
狀態的函數onFulfilled
或者處理rejected
狀態的函數onRejected
在運行時出現異常應該進行捕獲而且傳遞給下一個then()
的處理rejected
狀態的函數onRejected
。
這裏咱們先讓全部的異常都交由當前then()
處理rejected
狀態的函數onRejected
,後面再進行優化。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => { }; } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => { }; } if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 try { // then處理成功的函數onFulfilled中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onFulfilled(this.value); } catch (e) { onRejected(e); } } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 try { // then處理失敗的函數onRejected中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onRejected(this.value); } catch (e) { onRejected(e); } } } }
在原生的Promise
中,executor
函數是同步執行的,而then()
方法是異步執行故排在同步執行以後。
可是咱們的Promise
卻沒有作到這一點,下面的實驗將說明這個問題
<script src="./Promise核心.js"></script> <script> "use strict"; let p1 = new MyPromise((resolve, reject) => { reject("失敗"); }).then( null, error => { console.log(error); // 先打印 失敗 } ) console.log("hello,Promise"); // 後打印 hello,Promise </script>
最簡單的解決方案就是爲then()
中處理成功或處理失敗的函數運行外套上一個setTimeout
,讓其處理排在線程同步任務執行以後再進行執行。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => { }; } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => { }; } if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理成功的函數onFulfilled中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onFulfilled(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理失敗的函數onRejected中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onRejected(this.value); } catch (e) { onRejected(e); } }) } } }
此時咱們的代碼仍然具備一個問題,即在執行函數executor
中使用setTimeout
時,下面的then()
會進行阻塞。
這是由於當前Promise
狀態是pending
而then()
方法中並無對pending
狀態進行處理的策略所致使的。
<script src="./Promise核心.js"></script> <script> "use strict"; new MyPromise((resolve, reject) => { setTimeout(() => { resolve("成功"); // 同步任務執行完三秒後纔會改變當前Promise狀態 }, 3000); }).then((success) => { // 可是這裏先執行了then,Promise狀態爲pending,故發生阻塞 console.log(success); // 阻塞了,不打印 }) </script>
既然當前Promise
狀態是pending
,3秒後狀態才發生改變,那麼咱們就能夠經過不斷的循環來看看它什麼時候改變狀態。
因此第一步是定義一個執行異步的數組。而後再將then()
中處理正確的函數onFulfilled
與處理錯誤的函數onRejected
壓進去。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => { }; } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => { }; } if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理成功的函數onFulfilled中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onFulfilled(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理失敗的函數onRejected中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onRejected(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled, onRejected, }); } } }
當數組壓入完成後,執行函數executor
會去調用resolve()
或者reject()
改變當前Promise
狀態。
因此咱們還須要在resolve()
與reject()
方法中對異步的數組處理函數進行調用。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => { }; } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => { }; } if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理成功的函數onFulfilled中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onFulfilled(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理失敗的函數onRejected中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onRejected(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled, onRejected, }); } } }
上面咱們對同步執行函數executor
調用then()
方法中可能出現的異常進行了處理。
就是下面這一段代碼。
if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理成功的函數onFulfilled中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onFulfilled(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理失敗的函數onRejected中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onRejected(this.value); } catch (e) { onRejected(e); } }) }
可是咱們尚未對異步執行函數executor
調用then()
方法中可能出現的異常進行處理。
if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled, onRejected, }); } }
這會致使下面這樣的使用場景出現問題。
<script src="./Promise核心.js"></script> <script> "use strict"; new MyPromise((resolve, reject) => { setTimeout(() => { resolve("成功"); }, 3000); }).then((success) => { throw new Error("自定義異常拋出"); // 直接在處理成功狀態的函數onFulfilled中拋出了異常,顯然是不符合原生Promise的 }); </script>
那麼咱們就來加上異常捕獲便可,這裏仍是先傳遞給當前then()
處理rejected
狀態的函數,後面會作修改。
由於原版Promise
會傳遞給下一個then()
中處理rejected
狀態的函數,而不是當前then()
。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => { }; } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => { }; } if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理成功的函數onFulfilled中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onFulfilled(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理失敗的函數onRejected中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onRejected(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { try { // 異步executor改變狀態對其then中的onFulfilled進行異常捕獲 onFulfilled(value); } catch (e) { onRejected(e); } }, onRejected: value => { try { // 異步executor改變狀態對其then中的onRejected進行異常捕獲 onRejected(value); } catch (e) { onRejected(e); } } }); } } }
對於原生的Promise
來說,每個then()
最後返回的都是一個新的Promise
。因此才能達到支持不斷的then()
進行鏈式操做,因此咱們也能夠這樣作。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => { }; } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => { }; } return new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理成功的函數onFulfilled中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onFulfilled(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理失敗的函數onRejected中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 onRejected(this.value); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { try { // 異步executor改變狀態對其then中的onFulfilled進行異常捕獲 onFulfilled(value); } catch (e) { onRejected(e); } }, onRejected: value => { try { // 異步executor改變狀態對其then中的onRejected進行異常捕獲 onRejected(value); } catch (e) { onRejected(e); } } }); } }); } }
如今咱們的Promise
已經支持then()
的鏈式操做了,可是上面代碼仍是遺留了幾個問題。
1.
then()
尚未返回值,返回普通值該怎麼處理,返回一個新的Promise
該怎麼處理2.沒有異常傳遞,原生
Promise
中的then()
當拋出異常時應該進行捕獲並傳遞給下一個then()
3.不支持
then()
穿透4.不支持類型限制
接下來繼續對代碼作出優化調整。
在原生的Promise
中每個then()
所產生的Promise
默認狀態都是fulfilled
,若是當前then()
返回是一個值的話那麼下一個then()
將接受到該值。
這個也很是簡單,代碼接收一下每個onFulfilled()
與onRejected()
的返回值就好,並使用resolve()
改變狀態爲fulfilled
以及將值進行傳遞給下一個then()
。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => { }; } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => { }; } return new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理成功的函數onFulfilled中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 let result = onFulfilled(this.value); resolve(result); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { // then處理失敗的函數onRejected中出現異常,交由當前then處理失敗的函數onRejected函數進行處理。這個後面會作優化 let result = onRejected(this.value); resolve(result); } catch (e) { onRejected(e); } }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { try { // 異步executor改變狀態對其then中的onFulfilled進行異常捕獲 let result = onFulfilled(value); resolve(result); } catch (e) { onRejected(e); } }, onRejected: value => { try { // 異步executor改變狀態對其then中的onRejected進行異常捕獲 let result = onRejected(value); resolve(result); } catch (e) { onRejected(e); } } }); } }); } }
這樣咱們的then()
就支持返回普通值了。
<script src="./Promise核心.js"></script> <script> "use strict"; new MyPromise((resolve, reject) => { setTimeout(() => { resolve("成功"); }, 3000); }).then((success) => { return "hello"; }).then((success)=>{ console.log(success); // hello }); </script>
在上面的代碼中,then()
方法裏的處理成功函數onFulfilled
以及處理失敗函數onRejected
在代碼執行時拋出的異常都會統一進行捕獲而且傳遞給當前then()
方法處理失敗的函數onRejected
。
這個與原生的Promise
有出入,對於原生Promise
來說應該是傳遞給下一個then()
進行處理而不是當前then()
。
改動也很是簡單,將原來發生異常傳遞的函數onRejected()
改成reject()
便可,這就是傳遞給下一個then()
。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => { }; } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => { }; } return new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { let result = onFulfilled(this.value); resolve(result); } catch (e) { reject(e); // 傳遞給下一個then } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { let result = onRejected(this.value); resolve(result); } catch (e) { reject(e); // 傳遞給下一個then } }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { try { let result = onFulfilled(value); resolve(result); } catch (e) { reject(e); // 傳遞給下一個then } }, onRejected: value => { try { let result = onRejected(value); resolve(result); } catch (e) { reject(e); // 傳遞給下一個then } } }); } }); } }
<script src="./Promise核心.js"></script> <script> "use strict"; new MyPromise((resolve, reject) => { setTimeout(() => { resolve("成功"); }, 3000); }).then((success) => { throw new Error("新錯誤"); }).then(null, error => { console.log(error); // 上一個then的錯誤成功由該then接收 }); </script>
在原生的Promise
中是支持then()
的穿透傳值的。
<script> "use strict"; new Promise((resolve, reject) => { resolve("成功"); }) .then() // 穿透 .then( success => { console.log(success); // 成功 }, error => { console.log(error); }) </script>
可是咱們的Promise
卻不支持。
<script src="./Promise核心.js"></script> <script> "use strict"; new MyPromise((resolve, reject) => { resolve("成功"); }) .then() // 不支持穿透 .then( success => { console.log(success); }, error => { console.log(error); }) </script>
緣由在於若是沒有對then()
進行傳遞參數,那麼內部實際上是會建立兩個空函數。
咱們只須要在空函數內部返回this.value
便可。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => this.value; // 支持穿透 } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => this.value; // 支持穿透 } return new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { let result = onFulfilled(this.value); resolve(result); } catch (e) { reject(e); // 傳遞給下一個then } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { let result = onRejected(this.value); resolve(result); } catch (e) { reject(e); // 傳遞給下一個then } }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { try { let result = onFulfilled(value); resolve(result); } catch (e) { reject(e); // 傳遞給下一個then } }, onRejected: value => { try { let result = onRejected(value); resolve(result); } catch (e) { reject(e); // 傳遞給下一個then } } }); } }); } }
原生的Promise
支持返回一個新的Promise
,可是咱們的Promise
如今還不支持。
其實也很簡單,判斷一下then()
中兩個函數返回的是否是一個新的Promise
,若是是的話則使用其then()
方法將其中resolve()
或reject()
的值進行傳遞。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => this.value; // 支持穿透 } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => this.value; // 支持穿透 } return new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { let result = onFulfilled(this.value); if (result instanceof MyPromise) { // 判斷是否返回Promise對象 result.then(resolve, reject); } else { resolve(result); // 改變狀態並將值交由下一個then接收 } } catch (e) { reject(e); // 傳遞給下一個then } }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 try { let result = onRejected(this.value); if (result instanceof MyPromise) { // 判斷是否返回Promise對象 result.then(resolve, reject); } else { resolve(result); // 改變狀態並將值交由下一個then接收 } } catch (e) { reject(e); // 傳遞給下一個then } }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { try { let result = onFulfilled(value); if (result instanceof MyPromise) { // 判斷是否返回Promise對象 result.then(resolve, reject); } else { resolve(result); // 改變狀態並將值交由下一個then接收 } } catch (e) { reject(e); // 傳遞給下一個then } }, onRejected: value => { try { let result = onRejected(value); if (result instanceof MyPromise) { // 判斷是否返回Promise對象 result.then(resolve, reject); } else { resolve(result); // 改變狀態並將值交由下一個then接收 } } catch (e) { reject(e); // 傳遞給下一個then } } }); } }); } }
能夠觀察到上面的then()
方法中有不少重複代碼,因此咱們須要對重複代碼作一下優化。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => this.value; // 支持穿透 } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => this.value; // 支持穿透 } return new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 this.parse(onFulfilled(this.value), resolve, reject); }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 this.parse(onRejected(this.value), resolve, reject); }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { this.parse(onFulfilled(value), resolve, reject); }, onRejected: value => { this.parse(onRejected(value), resolve, reject); } }); } }); } parse(result, resolve, reject) { try { if (result instanceof MyPromise) { // 判斷是否返回Promise對象 result.then(resolve, reject); } else { resolve(result); // 改變狀態並將值交由下一個then接收 } } catch (e) { reject(e); // 向下傳遞異常 } } }
咱們都知道then()
會建立一個Promise
並返回,可是原生的Promise
不支持then()
將本身建立的Promise
進行返回
<script> "use strict"; let p1 = new Promise((resolve, reject) => { resolve("成功"); }) let p2 = p1.then( // 因爲then中的處理成功與處理失敗的函數是屬於異步執行。因此會先將建立好的Promise對象返回再運行其中的處理成功函數與處理失敗函數。 success => { return p2; } ) // Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise> </script>
可是咱們的Promise
還不支持這一點,因此須要改一改代碼。
解決的思路也很簡單,在運行失敗或處理函數時判斷一下本次返回的值是否等同於建立的Promise
對象。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => this.value; // 支持穿透 } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => this.value; // 支持穿透 } let promise = new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 this.parse(promise, onFulfilled(this.value), resolve, reject); }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 this.parse(promise, onRejected(this.value), resolve, reject); }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { this.parse(promise, onFulfilled(value), resolve, reject); }, onRejected: value => { this.parse(promise, onRejected(value), resolve, reject); } }); } }); return promise; // 同步,先返回。onFulfilled與onRejected因爲套了setTimeout,是異步執行。 } parse(promise, result, resolve, reject) { if (promise == result) { throw new TypeError("Chaining cycle detected"); } try { if (result instanceof MyPromise) { // 判斷是否返回Promise對象 result.then(resolve, reject); } else { resolve(result); // 改變狀態並將值交由下一個then接收 } } catch (e) { reject(e); // 向下傳遞異常 } } }
使用 Promise.resolve()
方法能夠快速的返回一個狀態是fulfilled
的Promise
對象。
使用 Promise.reject()
方法能夠快速的返回一個狀態是rejected
的Promise
對象。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => this.value; // 支持穿透 } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => this.value; // 支持穿透 } let promise = new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 this.parse(promise, onFulfilled(this.value), resolve, reject); }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 this.parse(promise, onRejected(this.value), resolve, reject); }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { this.parse(promise, onFulfilled(value), resolve, reject); }, onRejected: value => { this.parse(promise, onRejected(value), resolve, reject); } }); } }); return promise; // 同步,先返回。onFulfilled與onRejected因爲套了setTimeout,是異步執行。 } parse(promise, result, resolve, reject) { if (promise == result) { throw new TypeError("Chaining cycle detected"); } try { if (result instanceof MyPromise) { // 判斷是否返回Promise對象 result.then(resolve, reject); } else { resolve(result); // 改變狀態並將值交由下一個then接收 } } catch (e) { reject(e); // 向下傳遞異常 } } static resolve(value) { return new MyPromise((resolve, reject) => { if (value instanceof MyPromise) { value.then(resolve, reject); } else { resolve(value); } }); } static reject(value) { return new MyPromise((resolve, reject) => { reject(value); }); } }
使用Promise.all()
方法能夠同時執行多個並行異步操做,好比頁面加載時同進獲取課程列表與推薦課程。任何一個 Promise
執行失敗就會調用 catch
方法,成功後返回 Promise
結果的有序數組。(Ps:咱們這個Promise
沒有實現catch
方法)
使用Promise.race()
處理容錯異步,和race
單詞同樣哪一個Promise
快用哪一個,哪一個先返回用哪一個。
class MyPromise { static PENDING = "pending"; static FUFILLED = "fulfilled"; static REJECTED = "rejected"; constructor(executor) { this.status = MyPromise.PENDING; // 初始狀態爲準備狀態 this.value = null; // 初始值 this.callbacks = []; // 若是是一個異步操做,則放入該數組中 try { executor(this.resolve.bind(this), this.reject.bind(this)); // 傳遞形參,運行executor函數 } catch (e) { this.status = MyPromise.REJECTED; // 異常發生改變狀態 this.reject(e); // 記錄異常信息 } } resolve(value) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.FUFILLED; this.value = value; this.callbacks.map(callback => { // // 調用處理異步executor裏resolve的方法。 callback.onFulfilled(value); }) } } reject(reason) { if (this.status == MyPromise.PENDING) { // 限制 this.status = MyPromise.REJECTED; this.value = reason; this.callbacks.map(callback => { // 調用處理異步executor裏reject的方法。 callback.onRejected(reason); }) } } then(onFulfilled, onRejected) { if (typeof onFulfilled != "function") { // 若是傳入的不是一個函數,默認建立空函數 onFulfilled = () => this.value; // 支持穿透 } if (typeof onRejected != "function") { // 若是傳入的不是一個函數,默認建立空函數 onRejected = () => this.value; // 支持穿透 } let promise = new MyPromise((resolve, reject) => { // 返回一個新的Promise if (this.status == MyPromise.FUFILLED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 this.parse(promise, onFulfilled(this.value), resolve, reject); }) } if (this.status == MyPromise.REJECTED) { // 狀態改變時執行 setTimeout(() => { // 晚於線程同步任務執行 this.parse(promise, onRejected(this.value), resolve, reject); }) } if (this.status == MyPromise.PENDING) { // 若是當前Promise是等待處理狀態,則將處理成功的函數與處理失敗的函數壓入異步數組。 this.callbacks.push({ onFulfilled: value => { this.parse(promise, onFulfilled(value), resolve, reject); }, onRejected: value => { this.parse(promise, onRejected(value), resolve, reject); } }); } }); return promise; // 同步,先返回。onFulfilled與onRejected因爲套了setTimeout,是異步執行。 } parse(promise, result, resolve, reject) { if (promise == result) { throw new TypeError("Chaining cycle detected"); } try { if (result instanceof MyPromise) { // 判斷是否返回Promise對象 result.then(resolve, reject); } else { resolve(result); // 改變狀態並將值交由下一個then接收 } } catch (e) { reject(e); // 向下傳遞異常 } } static resolve(value) { return new MyPromise((resolve, reject) => { if (value instanceof MyPromise) { value.then(resolve, reject); } else { resolve(value); } }); } static reject(value) { return new MyPromise((resolve, reject) => { reject(value); }); } static all(value) { return new MyPromise((resolve, reject) => { const values = []; // 記錄當前有多少promise狀態是成功 promise.forEach((promise) => { promise.then(value => { values.push(value); if (values.length == promise.length) { resolve(values); // 若是都成功,當前all返回的promise則狀態爲fulfilled。 } }, reason => { reject(reason); // 若是有一個promise錯誤,則當前all返回的promise則爲拒絕 }) }); }); } static race(value) { return new MyPromise((resolve, reject) => { value.forEach(promise => { promise.then(value => { // 若是循環中的promise狀態爲fulfilled,則當前的race建立的promise狀態也爲resolve resolve(value); }, reason => { reject(value); // 同上 }) }) }) } }