前端面試?這份手擼Promise請你收下

前言

  如今不少大廠面試前端都會要求可以手動的寫出一個Promise,因此這裏整理了一份手寫的Promise前端

  絕對詳細,功能絕對強大。若是你不瞭解Promise的基本使用,那麼本篇文章可能不太適合你,若是你對Promise有過一些瞭解,那麼這篇文章絕對是你進階的好幫手。面試

  除開catch()以及finally()allSettled接口沒實現以外,其餘的全部原生Promise支持的功能此手寫的Promise都支持。數組

  書寫Promise的難度其實就在於then()方法的鏈式調用以及值穿透傳遞,其餘的其實都還好。promise

  讓這篇文章滾進你的收藏夾吧!異步

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執行函數

  原生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>

image-20200815121254320

  這是因爲咱們在執行函數中調用了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狀態限制

  當前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;

                }
        }
}

Promise執行異常

  在執行函數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;

                }
        }
}

then方法基礎實現

  原生的Promise狀態改變後,能夠執行其下的then()方法,因此咱們須要來封裝出一個then()方法。

  then()方法接收兩個函數,第一個函數onFulfilled用於處理上一個Promisefulfilled狀態,第二個函數onRejected用於處理上一個Promiserejected狀態。

  而且then()方法中的這兩個函數都應該具備一個形參,用於接收到Promiseresolve()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方法參數優化

  上面已經說過,then()方法具備兩個參數,這兩個參數分別對應兩個函數用來處理上一個Promsieresolve()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方法異常捕獲

  當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);
                        }
                }
        }
}

then方法異步執行

  在原生的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狀態是pendingthen()方法中並無對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,
                        });
                }
        }
}

異步執行函數的then異常捕獲

  上面咱們對同步執行函數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>

image-20200816143518914

  那麼咱們就來加上異常捕獲便可,這裏仍是先傳遞給當前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);
                                        }
                                }
                        });
                }
        }
}

then方法鏈式操做

  對於原生的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.不支持類型限制

  接下來繼續對代碼作出優化調整。

then中返回普通值

  在原生的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中的異常傳遞

  在上面的代碼中,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>

then穿透功能實現

  在原生的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
                                                }
                                        }
                                });
                        }
                });


        }
}

then返回Promise

  原生的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的代碼優化

  能夠觀察到上面的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返回類型限制

  咱們都知道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);  // 向下傳遞異常
                }
        }
}

resolve與reject實現

  使用 Promise.resolve() 方法能夠快速的返回一個狀態是fulfilledPromise對象。

  使用 Promise.reject() 方法能夠快速的返回一個狀態是rejectedPromise對象。

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);
                });
        }
}

all與race實現

  使用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);  // 同上
                                })
                        })
                })
        }
}
相關文章
相關標籤/搜索