Promise的源碼記錄

Promise 源碼記錄(上課過程記錄的筆記)

Promise.js代碼:

僅僅實現了簡單的then,catch和Promise對象的執行器函數

(function (window){   /** IIFE */
    const PENDING ='pending';
    const RESOLVED ='resolved';
    const REJECTED = 'rejected';
    function Promise(exector){
        let self = this;
        self.status = PENDING;
        /**
         * callbacks裏面存儲的數據類型爲:{onResolved,onRejected}
         */
        self.callbacks = [];
        self.data = undefined;
        function resolve(value){
            if(self.status === PENDING){
                self.data = value;
                self.status = RESOLVED;
                if(self.callbacks.length > 0){
                    self.callbacks.forEach(callbackObj => {
                        setTimeout(() => {
                            callbackObj.onResolved(value);
                        });
                    });
                }
                
            }
        }
        function reject(reasen){
            if(self.status === PENDING){
                self.data = reasen;
                self.status = REJECTED;
                if(self.callbacks.length > 0){
                    self.callbacks.forEach(callbackObj => {
                        setTimeout(() => {
                            callbackObj.onRejected(reason);
                        });
                    });
                }
            }
        }
        try{
            exector(resolve,reject);
        }catch(error){
            reject(error);
        }
    }

    /** 
     * 定義Promise的then方法實現回調
     */
    Promise.prototype.then = function(onResolved, onRejected){
        /**首先定義兩個回調函數的形式
         * 1. 如果兩個回調時函數,則直接返回
         * 2. 如果兩個回調函數不是函數類型,強制其爲函數
         */
        onResolved = typeof onResolved === 'function' ? onResolved : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : reasen => {throw reason};
        const self = this;
        return new Promise((resolve, reject) => {
            /** 直接將RESOLVED/REJECTED狀態下的執行器封裝成一個函數 */
            function handle(callback){
                /** 這裏要把執行函數放入異步隊列中 */
                /**
                 * 此處要定義Promise的狀態,分爲三種情況
                 * 1. 拋出異常,直接執行reject
                 * 2. 返回的值是Promise,則新的Promise的結果和狀態由上一次的結果決定
                 * 3. 返回的值不是Promise,則新的Promise直接成功
                 */
                try {
                    const result = callback(self.data);
                    if(result instanceof Promise){
                        result.then(resolve, reject);
                    }else{
                        resolve(result);
                    }
                } catch (reason) {
                    reject(reason);
                }
            }
            /**
             * 新的Promise的狀態要根據onResolved/onRejected的執行結果來決定
             */
            if(self.status === RESOLVED){
                setTimeout(() => {
                    handle(onResolved);
                });
            }else if(self.status === REJECTED){
                setTimeout(() => {
                    handle(onRejected);
                });
            }else{
                /**
                 * 如果是PENDING狀態,要把回調函數保存起來
                 * 但是不能直接去存,因爲要根據之前的結果來定義新的Promise的狀態
                 * 下面不需要異步調用,因爲異步操作在Promise的執行器中已經做了
                 */
                self.callbacks.push({
                    onResolved(){
                        handle(onResolved);
                    },
                    onRejected(){
                        handle(onRejected);
                    }
                });
            }
        });
    }

    /** 定義catch方法 */
    Promise.prototype.catch = function(onRejected){
        this.then(undefined, onRejected);
    }
    /** 向外暴露Promise */
    window.Promise = Promise
})(window)

測試用的index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Promise</title>
    <script src="./Promise.js"></script>
</head>
<body>
    <script type="text/javascript">
        const p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(5);
            }, 3000);
        });
        p1.then(value => {
            console.log("The anwser is successful, and the result is :", value);
            return new Promise(() => {});
        }).then(value => {
            console.log("The next result is:", value);
        }).catch(error => {
            console.log("The error is :", error)
        });
    </script>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章