promise簡單實現

function isFunction(fn){
    return Object.prototype.toString.call(fn) === '[object Function]';
}

let ST = {
    pending: 0,
    resolved: 1,
    rejected: 2
}

function Promise(fn){
    let self = this;
    self.status = ST.pending;
    self.value = '';
    self.reason = '';
    self.resolveFns = [];
    self.rejectFns = [];

    //setTimeout延遲執行,將reslove執行放在下個循環,保證then方法先於它執行
    function resolve(val){
        setTimeout(() => {
            if(self.status == ST.pending){
                self.status = ST.resolved;
                self.value = val;
                //用數組保存回調,是爲了處理一個promise掛載多個then的狀況
                //注意不是鏈式,這種場景不多出現
                /*
                形如:
                promise.then(resolve1,reject1)
                promise.then(resolve2,reject2)
                promise.then(resolve3,reject3)
                */
                //在鏈式調用中,該數組一般只會有一個項,就是當前promise的下一個then裏面的resolve函數
                //且每次執行,一般都是一個新Promise的resolve數組
                self.resolveFns.forEach(fn => fn());
            }
        })
    }

    function reject(val){
        setTimeout(() => {
            if(self.status == ST.pending){
                self.status = ST.rejected;
                self.reason = val;
                self.rejectFns.forEach(fn => fn());
            }
        })
    }

    //執行出問題,直接reject,Promise的錯誤默認不會拋出到全局
    try{
        fn(resolve,reject);
    }
    catch(err){
        reject(err);
    }
}

Promise.prototype.then = function(onResolve,onReject){
    let self = this;

    //then每次執行都返回一個新的Promise,then方法要處理前一個promise的三種狀態
    return new Promise(function(resolve,reject){
        function handle(value,thenFn){
            let res = isFunction(thenFn) && thenFn(value) || value;
            if(res instanceof Promise){
                res.then(resolve,reject);
            }
            else{
                resolve(res);
            }
        }
    
        //處理三種狀態
        //fn函數體裏,若是有錯誤; 會執行try catch裏的 reject方法,執行then this.state就是rejected
        //若是沒錯誤且沒異步,resolve this.state就是resolved
        //若是沒錯誤且有異步,this.state就是pending
        if(self.status == ST.pending){
            self.resolveFns.push(resloveHandle);
            self.rejectFns.push(rejectHandle);
        }
        else if(self.status == ST.resolved){
            self.handle(self.value,onResolve);
        }
        else if(this.status == ST.rejected){
            self.handle(self.reason,onReject);
        }
    })
}

Promise.prototype.catch = function(onReject){
    return this.then(undefined, onReject);
}

//finally不是promise的末尾,後面還能夠有then,因此value和reason必須能夠向下傳遞
Promise.prototype.finally = function(fn){
    let P = this.constructor;
    return this.then(
        value => P.resolve(fn()).then(() => value),
        reason => P.resolve(fn()).then(() => throw reason);
    )
}

//done做爲promise的末尾,用於收集全部可能的報錯,catch方法捕捉全部錯誤,並拋出
Promise.prototype.done = function(resolve,reject){
    return this.then(resolve, reject).catch(function(reason){
        setTimeout(function(){
            throw reason;
        });
    })
}

Promise.resolve = function(val){
    return new Promise((resolve) => {
        resolve(val);
    })
}

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

Promise.race = function(promises){
    let len = promises.length;
    
    return new Promise(function(resolve,reject){
        while(len--){
            promises[len].then(resolve,reject);
        }
    })
}

Promise.all = function(promises){
    let len = promises.length,
        results = [];

    return new Promise(function(resolve,reject){
        //用一個數組收集單個promise執行後的結果,收集滿數組全部結果,即是全部執行成功
        function reslove(index){
            return function(value){
                results[index] = value;
                if(results.length == len){
                    reslove(results);
                }
            }
        }

        while(len--){
            promises[len].then(resolve(len),reject);
        }
    })
}
相關文章
相關標籤/搜索