手寫一款符合Promise/A+規範的Promise

手寫一款符合Promise/A+規範的Promise

長篇預警!有點長,能夠選擇性觀看。若是對Promise源碼不是很清楚,仍是推薦從頭看,相信你認真從頭看到尾,而且去實際操做了,確定會有收穫的。主要是代碼部分有點多,不過好多都是重複的,沒必要擔憂git

Promise的一些用法在此很少贅述,本篇主要帶領你手寫一個Promise源碼,學完你就會發現:Promise沒有你想象中的那麼難github

本篇大概分爲如下步驟

  • 實現簡單的同步Promise
  • 增長異步功能
  • 增長鏈式調用then
  • 增長catch finally方法
  • 增長all race 等方法
  • 實現一個promise的延遲對象defer
  • 最終測試

實現簡單的同步Promise

先大概說一下基本概念:
Promise內部維護着三種狀態,即pending,resolved和rejected。初始狀態是pending,狀態能夠有pending--->relolved,或者pending--->rejected.不能從resolve轉換爲rejected 或者從rejected轉換成resolved.
即 只要Promise由pending狀態轉換爲其餘狀態後,狀態就不可變動。
ok.知道了這些後,咱們開始手擼代碼:npm

注意觀看序號 1 2 3 4 5 ...數組

function Promise(executor){
    let that = this;
    /** 2 定義初始的一些變量 */
    that.status = 'pending';
    that.value = null;
    that.reason = null;
    
    /** 3 定義初始的成功和失敗函數 */
    function resolve(value){
        /** 4 判斷狀態是否是初始狀態pending 
         *    是就轉換狀態 不然不轉換 
         *    確保狀態的變化後的不可變性 */
        if(that.status === 'pending'){
            that.status = 'resolved';
            that.value = value;
        }
    }
    function reject(reason){
        /** 5 同上 */
        if(that.status === 'pending'){
            that.status = 'rejected';
            that.reason = reason;
        }
    }
    /**
     * 1 Promise中首先傳了一個executor,它是一個函數
     *   executor函數中又傳了兩個函數,分別是resolve和reject
     *   很顯然 resolve是成功回調,reject是失敗的回調
     */
    executor(resolve,reject);
}

/** 6 在Promise原型上面定義then方法
 *    then方法上面有兩個回調 一個是成功後的方法 另外一個是失敗後的方法
 *    根據成功或失敗的狀態去執行相關成功onFilfulled()或者失敗onRejected()的回調方法
 */
Promise.prototype.then = function(onFilfulled,onRejected){
    let that = this;
    if(that.status === 'resolved'){
        /** 7 若是狀態已經變動爲resolved 
         *    說明resolve方法已經被調用
         *    那麼此時就執行成功的回調函數onFilfulled
         *    並傳入參數 that.value
         * */
        onFilfulled(that.value);
    }
    if(that.status === 'rejected'){
        /** 8 同上
         *    傳入參數 that.reason
         */
        onRejected(that.reason);
    }
}

module.exports = Promise;

經過require()引入手擼的Promisepromise

let Promise = require('./myPromise');

let p1 = ()=>{
    return new Promise((resolve,reject)=>{
        resolve('success.1');
    });
}

p1().then((data)=>{
    console.log(data); // 打印 success.1
},(err)=>{
    console.log(err);
});

ok.經調用發現 此代碼能夠實現部分Promise的功能,但僅僅是同步下才有效果。
那異步呢? 別急這就來~:異步

增長異步功能

注意觀看序號 1 2 3 4 5 ...函數

function Promise(executor){
    let that = this;
    that.status = 'pending';
    that.value = null;
    that.reason = null;
    /** 1 由於異步不是當即執行 狀態不會變動 成功或失敗的回調函數也不會執行
     *    因此先定義好存放成功或失敗回調函數的數組 
     *    以便將成功或失敗的回調函數先保存起來
     * */
    that.onFilFulledCallbacks = [];
    that.onRejectedCallbacks = [];

    function resolve(value){
        if(that.status === 'pending'){
            that.status = 'resolved';
            that.value = value;
            /** 3 發佈
             *    等待狀態發生變動
             *    狀態變動後 當即執行以前存放在相應數組中全部的成功或失敗的回調函數
             *    即 發佈
             */
            that.onFilFulledCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    function reject(reason){
        if(that.status === 'pending'){
            that.status = 'rejected';
            that.reason = reason;
            /** 4 同上 */
            that.onRejectedCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    executor(resolve,reject);
}

Promise.prototype.then = function(onFilfulled,onRejected){
    let that = this;
    if(that.status === 'resolved'){
        onFilfulled(that.value);
    }
    if(that.status === 'rejected'){
        onRejected(that.reason);
    }
    /** 2 訂閱
     *    由於是異步 狀態當時並無當即變動 因此狀態仍是pending
     *    此時須要把成功或者失敗的回調函數存放到對應的數組中
     *    等待狀態變動時 再從數組中拿出來去執行
     *    即 訂閱
     *    *存放數組時 爲了執行時方便 須要把回調函數的外層包裹一層空函數
     */
    if(that.status === 'pending'){
        that.onFilFulledCallbacks.push(function(){
            onFilfulled(that.value);
        });
    }
    if(that.status === 'pending'){
        that.onRejectedCallbacks.push(function(){
            onRejected(that.reason);
        });
    }
}

module.exports = Promise;

代碼測試:測試

let Promise = require('./myPromise');

let p1 = ()=>{
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve('success.1');
            // reject('fail.');
        },1500);
    });
}

p1().then((data)=>{
    console.log(data); // success.1
},(err)=>{
    console.log(err);
});

能夠看到 1.5s後 執行了resolve() 並打印了success.1,至此,咱們實現了異步的Promise.其實這裏的實現異步的思想就是發佈訂閱.ui

en~ok.高能預警🐯.接下來就稍稍複雜了 由於咱們要實現鏈式調用then。 要實現這個功能那咱們就要重寫then方法,並在then方法中從新返回一個Promise,只有這樣,才能夠實現屢次調用then.並且要新增一個解析返回值是否爲promise的函數.this

稍微捋下邏輯:

  • 若是一個then方法返回一個普通值的話,這個值會傳遞給下一個then中做爲resolve成功的結果
  • 若是一個then方法返回一個promise的話,會根據返回的promise是成功仍是失敗,決定下一個then是成功仍是失敗

👌 上代碼:

增長鏈式調用then

注意觀看序號 1 2 3 4 5 ...

function Promise(executor){
    let that = this;
    that.status = 'pending';
    that.value = null;
    that.reason = null;
    that.onFilFulledCallbacks = [];
    that.onRejectedCallbacks = [];

    function resolve(value){
        if(that.status === 'pending'){
            that.status = 'resolved';
            that.value = value;
            that.onFilFulledCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    function reject(reason){
        if(that.status === 'pending'){
            that.status = 'rejected';
            that.reason = reason;
            that.onRejectedCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    executor(resolve,reject);
}

Promise.prototype.then = function(onFilfulled,onRejected){
    let that = this;
    /** 1 讓promise2等於一個新的Promise 並將promise2返回 */
    let promise2 = new Promise((resolve,reject)=>{
        if(that.status === 'resolved'){
            /** 2 由於返回了promise2 
             *  而且第3步resolvePromiseRelation函數中傳遞了promise2
             *  而目前promise2並無拿到
             *  因此加一個定時器 異步執行 等到promise2拿到後 
             *  再去執行 resolvePromiseRelation()方法 並將promise2傳遞進去*/
            setTimeout(()=>{
                try{
                    let promise3 = onFilfulled(that.value);
                    /** 3 判斷新返回值是什麼類型的函數
                     *  並將當前的promise:promise2  新的返回值:promise3 
                     *  和 成功時回調:esolve  失敗時回調:reject 做爲參數傳進去 */
                    resolvePromiseRelation(promise2,promise3,resolve,reject);
                }catch(e){
                    reject(e);
                }
            },0);
        }
        if(that.status === 'rejected'){
            /** 同2 */
            setTimeout(()=>{
                try{
                    let promise3 = onRejected(that.reason);
                    /** 同3*/
                    resolvePromiseRelation(promise2,promise3,resolve,reject);
                }catch(e){
                    reject(e);
                }
            },0);
        }
        if(that.status === 'pending'){
            that.onFilFulledCallbacks.push(function(){
                /** 同2 */
                setTimeout(()=>{
                    try{
                        let promise3 = onFilfulled(that.value);
                        /** 同3*/
                        resolvePromiseRelation(promise2,promise3,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                },0);
            });
        }
        if(that.status === 'pending'){
            that.onRejectedCallbacks.push(function(){
                 /** 同2 */
                 setTimeout(()=>{
                    try{
                        let promise3 = onRejected(that.reason);
                        /** 同3*/
                        resolvePromiseRelation(promise2,promise3,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                },0);
            });
        }
    });
    /** 同1 */
    return promise2;
}

function resolvePromiseRelation(promise2,promise3,resolve,reject){
     /** 4 防止本身等待本身 一直循環等待 */
    if(promise2 === promise3){
        return reject(new TypeError('循環引用了!'));
    }
    /**  8 一個標示 表示當前沒有被調用過 
     *   確保resolve或者reject後的狀態不會再次發生變動
    */ 
    let called;
     /** 5 保證promise3是一個引用類型
      *  判斷新返回值promise3的類型 
      *  若是是普通值常量 就直接resolve導出 */
    if(promise3!==null&&(typeof promise3 === 'object'||typeof promise3 === 'function')){
        try{
            let then = promise3.then;
            /** 6 確保promise3是一個Promise
             *  判斷promise3的then方法
             *  若是存在 而且是一個function類型 
             *  就表示promise3是一個Promise */
            if(typeof then === 'function'){
                /** 9 執行promise3的then方法
                 *  由於promise3也是一個Promise
                 *  須要再次解析promise3的then方法
                 *  直到解析到最後的返回值不是一個Promise類型爲止
                 */
                then(promise3, (promise4)=>{
                    /** 同8 */
                    if(called) return;
                    called = true;
                    /** 10 遞歸解析新的返回值的類型
                     *  解析到返回值不是一個Promise類型爲止
                     */
                    resolvePromiseRelation(promise3,promise4,resolve,reject);
                },(r)=>{
                    /** 同8 */
                    if(called) return;
                    called = true;
                    reject(r);
                });
            }else{
                /** 7 此時promise3是一個普通對象 直接resolve() */
                resolve(promise3);
            }
        }catch(e){
            /** 同8 */
            if(called) return;
            called = true;
            reject(e);
        };
    }else{
        /** 同5 普通值直接resolve()*/
        resolve(promise3);
    }
}

module.exports = Promise;

ok. 至此 咱們已經實現了Promsie的異步和鏈式調用. Promise中比較複雜的部分咱們已經搞定了 接下來就是添加一些方法,其實這部分反而沒那麼複雜了.

catch : catch方法本質上就是一個then方法的變形,只有失敗時的回調 沒有成功時的回調
finally : finally方法的做用是無論 Promise 對象最後狀態如何,都會執行操做.其實說白了就是在then方法的成功和失敗的回調函數中都執行該方法就好了.

ok.老規矩 上代碼~

增長catch finally方法
function Promise(executor){
    let that = this;
    that.status = 'pending';
    that.value = null;
    that.reason = null;
    that.onFilFulledCallbacks = [];
    that.onRejectedCallbacks = [];

    function resolve(value){
        if(that.status === 'pending'){
            that.status = 'resolved';
            that.value = value;
            that.onFilFulledCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    function reject(reason){
        if(that.status === 'pending'){
            that.status = 'rejected';
            that.reason = reason;
            that.onRejectedCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    executor(resolve,reject);
}

Promise.prototype.then = function(onFilfulled,onRejected){
    /** 2 此處有個坑 若是隻寫1 不寫2的話
     *  會報一個TypeError :onRejected is not a function
     *  在此處給它一個默認的成功和失敗的回調函數就好 */
    onFilfulled = typeof onFilfulled === 'function'?onFilfulled:value=>value;
    onRejected = typeof onRejected ===  'function'?onRejected:err=>{throw err};
    let that = this;
    let promise2 = new Promise((resolve,reject)=>{
        if(that.status === 'resolved'){
            setTimeout(()=>{
                try{
                    let promise3 = onFilfulled(that.value);
                    resolvePromiseRelation(promise2,promise3,resolve,reject);
                }catch(e){
                    reject(e);
                }
            },0);
        }
        if(that.status === 'rejected'){
            setTimeout(()=>{
                try{
                    let promise3 = onRejected(that.reason);
                    resolvePromiseRelation(promise2,promise3,resolve,reject);
                }catch(e){
                    reject(e);
                }
            },0);
        }
        if(that.status === 'pending'){
            that.onFilFulledCallbacks.push(function(){
                setTimeout(()=>{
                    try{
                        let promise3 = onFilfulled(that.value);
                        resolvePromiseRelation(promise2,promise3,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                },0);
            });
        }
        if(that.status === 'pending'){
            that.onRejectedCallbacks.push(function(){
                 setTimeout(()=>{
                    try{
                        let promise3 = onRejected(that.reason);
                        resolvePromiseRelation(promise2,promise3,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                },0);
            });
        }
    });
    return promise2;
}

function resolvePromiseRelation(promise2,promise3,resolve,reject){
    if(promise2 === promise3){
        return reject(new TypeError('循環引用了!'));
    }
    let called;
    if(promise3!==null&&(typeof promise3 === 'object'||typeof promise3 === 'function')){
        try{
            let then = promise3.then;
            if(typeof then === 'function'){
                then(promise3, (promise4)=>{
                    if(called) return;
                    called = true;
                    resolvePromiseRelation(promise3,promise4,resolve,reject);
                },(r)=>{
                    if(called) return;
                    called = true;
                    reject(r);
                });
            }else{
                resolve(promise3);
            }
        }catch(e){
            if(called) return;
            called = true;
            reject(e);
        };
    }else{
        resolve(promise3);
    }
}

/** 1 直接返回this的then方法
 *  由於catch只捕獲錯誤 因此resolve直接爲null
 *  返回reject就好*/
Promise.prototype.catch = function(errFn){
    return this.then(null,errFn);
}

/** 3 finally實現起來也很簡單 
 *  分別在resolve和reject中執行fn就好 
 *  最後再把this返回出去就好
*/
Promise.prototype.finally = function(fn){
    this.then(()=>{
        fn();
    },()=>{
        fn();
    });
    return this;
}

module.exports = Promise;
增長all race resolve reject等方法
function Promise(executor){
    let that = this;
    that.status = 'pending';
    that.value = null;
    that.reason = null;
    that.onFilFulledCallbacks = [];
    that.onRejectedCallbacks = [];

    function resolve(value){
        if(that.status === 'pending'){
            that.status = 'resolved';
            that.value = value;
            that.onFilFulledCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    function reject(reason){
        if(that.status === 'pending'){
            that.status = 'rejected';
            that.reason = reason;
            that.onRejectedCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    executor(resolve,reject);
}

Promise.prototype.then = function(onFilfulled,onRejected){
    onFilfulled = typeof onFilfulled === 'function'?onFilfulled:value=>value;
    onRejected = typeof onRejected ===  'function'?onRejected:err=>{throw err};
    let that = this;
    let promise2 = new Promise((resolve,reject)=>{
        if(that.status === 'resolved'){
            setTimeout(()=>{
                try{
                    let promise3 = onFilfulled(that.value);
                    resolvePromiseRelation(promise2,promise3,resolve,reject);
                }catch(e){
                    reject(e);
                }
            },0);
        }
        if(that.status === 'rejected'){
            setTimeout(()=>{
                try{
                    let promise3 = onRejected(that.reason);
                    resolvePromiseRelation(promise2,promise3,resolve,reject);
                }catch(e){
                    reject(e);
                }
            },0);
        }
        if(that.status === 'pending'){
            that.onFilFulledCallbacks.push(function(){
                setTimeout(()=>{
                    try{
                        let promise3 = onFilfulled(that.value);
                        resolvePromiseRelation(promise2,promise3,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                },0);
            });
        }
        if(that.status === 'pending'){
            that.onRejectedCallbacks.push(function(){
                 setTimeout(()=>{
                    try{
                        let promise3 = onRejected(that.reason);
                        resolvePromiseRelation(promise2,promise3,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                },0);
            });
        }
    });
    return promise2;
}

function resolvePromiseRelation(promise2,promise3,resolve,reject){
    if(promise2 === promise3){
        return reject(new TypeError('循環引用了!'));
    }
    let called;
    if(promise3!==null&&(typeof promise3 === 'object'||typeof promise3 === 'function')){
        try{
            let then = promise3.then;
            if(typeof then === 'function'){
                then(promise3, (promise4)=>{
                    if(called) return;
                    called = true;
                    resolvePromiseRelation(promise3,promise4,resolve,reject);
                },(r)=>{
                    if(called) return;
                    called = true;
                    reject(r);
                });
            }else{
                resolve(promise3);
            }
        }catch(e){
            if(called) return;
            called = true;
            reject(e);
        };
    }else{
        resolve(promise3);
    }
}

Promise.prototype.catch = function(errFn){
    return this.then(null,errFn);
}
Promise.prototype.finally = function(fn){
    this.then(()=>{
        fn();
    },()=>{
        fn();
    });
    return this;
}

/** 1 直接在構造函數上增長all方法
 *  它返回的也是一個Promise
 *  等待參數數組中全部的promise都執行完畢後
 *  再返回結果
 */
Promise.all = function(values){
    return new Promise((resolve,reject)=>{
        /** 2 定義一個存放最終結果的數組result和一個index */ 
        let results = [];
        let index = 0;
        /** 3 定義一個方法addToArr()  
         *  讓index每次執行增長results數組元素的函數的時候都+1
         *  當index === values的長度的時候 說明此時全部promsie都執行完畢並放到的數組中
         *  而後直接resolve(results)就好了
        */
        function addToArr(key,value){
            index++;
            results[key] = value;
            /** 6 當知足條件時 說明全部的promise都執行完畢 直接resolve(results) */
            if(index === values.length){
                resolve(results);
            }
        }
        /** 4 循環values中的每一項promsie */
        for(let i = 0; i < values.length; i++){
            let current = values[i];
            /** 5 判斷每一項promise的返回值是否是一個Promsie
             *  是的話就執行該Promise的then方法 拿到返回值 並放到數組results中
             *  是一個普通值的話就直接將該值放到數組results中
             */
            if(current && current.then && typeof current.then === 'function'){
                current.then((value)=>{
                    /** 同5 把返回值放到數組results中*/
                    addToArr(i,value);
                },reject);
            }else{
                /** 同5 把返回值放到數組results中*/
                addToArr(i,current);
            }
        }
    });
}

/** race方法相比較於all方法簡單不少
 *  由於race中的promsie成功resolve一個 
 *  整個race就resolve */
Promise.race = function(values){
    return new Promise((resolve,reject)=>{
        /** 同4 */
        for(let i = 0; i < values.length; i++){
            let current = values[i];
            /** 同5 */
            if(current&&current.then&&typeof current.then === 'function'){
                /** 7 直接執行then就好 */
                current.then(resolve,reject);
            }else{
                /** 8 普通值直接resolve */
                resolve(current);
            }
        }
    });
}

// resolve方法
Promise.resolve = function(value){
    return new Promise((resolve,reject)=>{
        resolve(value);
    });
}
// reject方法
Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason);
    });
}

module.exports = Promise;
實現一個promise的延遲對象defer

此步是爲了測試咱們手寫的Promsie符不符合Promsie/A+規範,若是沒有defer的話,咱們在測試過程當中就會報一個TypeError: adapter.deferred is not a function.

其實寫完defer後,咱們就能夠去進行測試咱們手寫的Promsie符不符合Promsie/A+規範了。

即:本篇手寫一款符合Promise/A+規範的Promise的最終本爲:

function Promise(executor){
    let that = this;
    that.status = 'pending';
    that.value = null;
    that.reason = null;
    that.onFilFulledCallbacks = [];
    that.onRejectedCallbacks = [];

    function resolve(value){
        if(that.status === 'pending'){
            that.status = 'resolved';
            that.value = value;
            that.onFilFulledCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    function reject(reason){
        if(that.status === 'pending'){
            that.status = 'rejected';
            that.reason = reason;
            that.onRejectedCallbacks.forEach((fn)=>{
                fn();
            });
        }
    }
    try{
        executor(resolve,reject);
    }catch(e){
        reject(e);
    }
}

Promise.prototype.then = function(onFilfulled,onRejected){
    onFilfulled = typeof onFilfulled === 'function'?onFilfulled:value=>value;
    onRejected = typeof onRejected === 'function'?onRejected:err=>{throw err};
    let that = this;
    let promise2 = new Promise((resolve,reject)=>{
        if(that.status === 'resolved'){
            setTimeout(()=>{
                try{
                    let promise3 = onFilfulled(that.value);
                    resolvePromiseRelation(promise2,promise3,resolve,reject);
                }catch(e){
                    reject(e);
                }
            },0);
        }
        if(that.status === 'rejected'){
            setTimeout(()=>{
                try{
                    let promise3 = onRejected(that.reason);
                    resolvePromiseRelation(promise2,promise3,resolve,reject);
                }catch(e){
                    reject(e);
                }
            },0);
        }
        if(that.status === 'pending'){
            that.onFilFulledCallbacks.push(function(){
                setTimeout(()=>{
                    try{
                        let promise3 = onFilfulled(that.value);
                        resolvePromiseRelation(promise2,promise3,resolve,reject);
                    }catch(e){
                        reject(e);
                    }
                },0);
            });
            that.onRejectedCallbacks.push(function(){
                setTimeout(()=>{
                   try{
                       let promise3 = onRejected(that.reason);
                       resolvePromiseRelation(promise2,promise3,resolve,reject);
                   }catch(e){
                       reject(e);
                   }
               },0);
           });
        }
    });
    return promise2;
}

function resolvePromiseRelation(promise2,promise3,resolve,reject){
    if(promise2 == promise3){
        return reject(new TypeError('循環引用了!'));
    }
    let called;
    if(promise3!==null&&(typeof promise3 === 'object' || typeof promise3 === 'function')){
        try{
            let then = promise3.then;
            if(typeof then === 'function'){
                then.call(promise3, (promise4)=>{
                    if(called) return;
                    called = true;
                    resolvePromiseRelation(promise3,promise4,resolve,reject);
                },(r)=>{
                    if(called) return;
                    called = true;
                    reject(r);
                });
            }else{
                resolve(promise3);
            }
        }catch(e){
            if(called) return;
            called = true;
            reject(e);
        };
    }else{
        resolve(promise3);
    }
}

Promise.prototype.catch = function(errFn){
    return this.then(null,errFn);
}
Promise.prototype.finally = function(fn){
    this.then(()=>{
        fn();
    },()=>{
        fn();
    });
    return this;
}

Promise.all = function(values){
    return new Promise((resolve,reject)=>{
        let results = [];
        let index = 0;
        function addToArr(key,value){
            index++;
            results[key] = value;
            if(index === values.length){
                resolve(results);
            }
        }
        for(let i = 0; i < values.length; i++){
            let current = values[i];
            if(current && current.then && typeof current.then === 'function'){
                current.then((value)=>{
                    addToArr(i,value);
                },reject);
            }else{
                addToArr(i,current);
            }
        }
    });
}

Promise.race = function(values){
    return new Promise((resolve,reject)=>{
        for(let i = 0; i < values.length; i++){
            let current = values[i];
            if(current&&current.then&&typeof current.then === 'function'){
                current.then(resolve,reject);
            }else{
                resolve(current);
            }
        }
    });
}

Promise.resolve = function(value){
    return new Promise((resolve,reject)=>{
        resolve(value);
    });
}

Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason);
    });
}
// 實現一個promise的延遲對象 defer
Promise.defer = Promise.deferred = function(){
    let dfd = {};
    dfd.promise = new Promise((resolve, reject)=>{
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd;
}
module.exports = Promise;
最終測試
  • 測試當前代碼是否符合Promise/A+規範
  • 全局安裝 npm i -g promises-aplus-tests
  • 文件所在目錄運行如下命令 (例如你的文件名爲:MyPrommise.js)
  • promise-aplus-tests MyPrommise.js
  • 等待
  • ok.

clipboard.png

源碼在github上,寫文章不易,歡迎star或fork,thx~
github

相關文章
相關標籤/搜索