手写promsie,理解更深刻

89 阅读1分钟

// 实现 Promise.all 方法

    function MyPromise(executor){
        var that = this;
        that.status = 'Pending';
        that.resolveValue = null;
        that.rejectReason = null;
        that.ResolveCallBackList = [];
        that.RejectCallBackList = [];

        function resolve(value){
            if(that.status == 'Pending'){
                that.status = 'Fulfilled';
                that.resolveValue = value;
                that.ResolveCallBackList.forEach(function (ele){
                    ele();
                })
            }
        }
        function reject(reason){
            if(that.status == 'Pending'){
                that.status = 'Rejected';
                that.rejectReason = reason;
                that.RejectCallBackList.forEach(function (ele){
                    ele();
                })
            }
        }
        executor(resolve, reject);
    }
    MyPromise.prototype.then = function(onFulfilled, onRejected){
        if(!onFulfilled){
            onFulfilled = function(value){
                return value;
            }
        }
        if(!onRejected){
            onRejected = function(reason){
                throw new Error(reason);
            }
        }

        var that = this;
        var nextPromise = new MyPromise(function (resolve, reject){
            if(that.status == 'Pending'){
                that.ResolveCallBackList.push(function(){
                    try{
                        var nextResolveValue = onFulfilled(that.resolveValue);
                        ResolutionRetrunPromise(nextPromise, nextResolveValue, resolve, reject);
                    }catch(e){
                        reject(e);
                    }
                })
                that.RejectCallBackList.push(function(){
                    try{
                        var nextRejectValue = onRejected(that.rejectReason);
                        ResolutionRetrunPromise(nextPromise, nextRejectValue, resolve, reject);
                    }catch(e){
                        reject(e);
                    }
                })
            }
            if(that.status == 'Fulfilled'){
                try{
                    var nextResolveValue = onFulfilled(that.resolveValue);
                    ResolutionRetrunPromise(nextPromise, nextResolveValue, resolve, reject);
                }catch(e){
                    reject(e);
                }
            }
            if(that.status == 'Rejected'){
                try{
                    var nextRejectValue = onRejected(that.rejectReason);
                    ResolutionRetrunPromise(nextPromise, nextRejectValue, resolve, reject);
                }catch(e){
                    reject(e);
                }
            }
        })
        return nextPromise;
    }
    function ResolutionRetrunPromise(nextPromise, returnValue, resolve, reject){
        if(returnValue instanceof MyPromise){       // Promise 对象
            returnValue.then(function (value){
                resolve(value);
            }, function (reason){
                reject(reason);
            })
        }else{
            resolve(returnValue);
        }
    }
    MyPromise.prototype.catch = function(onRejected){
        return this.then(null, onRejected);
    }
    MyPromise.prototype.finally = function(callback){
        return this.then(function(value){
            callback();
            return value;
        }, function(reason){
            callback();
            throw reason;
        })
    }

    MyPromise.all = function(promiseArr){
        return new MyPromise(function (resolve, reject){
            var arr = [];
            var times = 0;
            for(let i=0; i<promiseArr.length; i++){
                var oPromise = promiseArr[i];
                if(typeof oPromise.then == 'function'){
                    oPromise.then(function (value){
                        processResult(i, value);
                    }, function (reason){
                        reject(reason);
                    })
                }else{
                    processResult(i, oPromise);
                }
            }
            function processResult(index, result){
                arr[index] = result;
                times++;
                if(times == promiseArr.length){
                    resolve(arr);
                }
            }
        })
    }
    MyPromise.race = function(promiseArr){
        return new MyPromise(function (resolve, reject){
            promiseArr.forEach(function (promise, index){
                promise.then(resolve, reject);
            })
        })
    }
    MyPromise.reject = function (reason) {
        return new MyPromise(function (resolve, reject) {
            reject(reason);
        });
    };
    MyPromise.resolve = function (val) {
        return new MyPromise(function (resolve, reject) {
            resolve(val);
        });
    };



    // 测试用例
    var mm = new MyPromise(function(resolve, reject){
        setTimeout( function(){
            resolve('成功结果');
        }, 50);
    })
    mm.then(function(success){
        console.log(success);   // 成功结果
    }).catch(function(error){
        console.log(error)
    }).finally(function(){
        //console.log(1)
    })

    // all
    let pro1 = new MyPromise(function(resolve, reject){
        setTimeout(() => {
            resolve('结果1');
        }, 100)
    })
    let pro2 = new MyPromise(function(resolve, reject){
        setTimeout(() => {
            resolve('结果2');
        }, 200)
    })
    MyPromise.all([pro1, pro2]).then(function(res){
        console.log(res);       // ["结果1", "结果2"]
    }).catch(function(error){
        console.log(error);
    })

    // race
    MyPromise.race([pro1, pro2]).then(function(res){
        console.log(res);       // 结果2
    }).catch(function(error){
        console.log(error);
    })