手写Promise以及相关的方法

41 阅读1分钟
class MyPromise{
    constructor(executor){
        this.initValue()
        this.initBind()
        executor(this.resolve,this.reject)
    }
    initValue(){
        //初始化值
        this.PromiseState = 'pending'
        this.PromiseResult = null
        //保存回调
        this.onFulfilledCallbacks = []
        this.onRejectedCallbacks = []
    }
    initBind(){
        //初始化移动this的指向
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value){
        if(this.PromiseState!='pending'){
            return
        }
        this.PromiseState = 'fulfilled'
        this.PromiseResult = value
        while(this.onFulfilledCallbacks.length){
            this.onFulfilledCallbacks.shift()(this.PromiseResult)
        }
    }
    reject(reason){
        if(this.PromiseState!='pending'){
            return
        }
        this.PromiseState = 'rejected'
        this.PromiseResult = reason
        while(this.onRejectedCallbacks.length){
            this.onRejectedCallbacks.shift()(this.PromiseResult)
        }
    }
    then(onFulfilled,onRejected){
        onFulfilled = typeof onFulfilled === 'function'? onFulfilled:val
        onRejected = typeof onRejected === 'function'? 
            onRejected:
            reason=>{throw new Error(reason)}
        
        let chainPromise = new MyPromise((resolve,reject)=>{
            const resolvePromise = cb=>{
                try{
                    const x = cb(this.PromiseResult)
                    if(this.PromiseResult === x){
                        throw new Error("error")
                    }
                    if(x instanceof MyPromise){
                        x.then(resolve,reject)
                    }else{
                        resolve(x)
                    }
                }catch(e){
                    reject(e)
                    throw new Error(e)
                }
            }
            if(this.PromiseState === 'fulfilled'){
                resolvePromise(onFulfilled)
            }else if(this.PromiseState === 'rejected'){
                resolvePromise(onRejected)
            }else{
                this.onFulfilledCallbacks.push(resolvePromise(this,onFulfilled))
                this.onRejectedCallbacks.push(resolvePromise(this,onRejected))
            }
        })
        return chainPromise
    }
    all(pros){
        let res = []
        let count = 0
        return new MyPromise((resolve,reject)=>{
            let handleArr = (value,index)=>{
                res[index] = value
                count++
                if(count == pros.length){
                    resolve(res)
                }
            }
            pros.forEach((pro,index)=>{
                if(pro instanceof MyPromise){
                    pro().then(res=>{
                       handleArr(res,index)
                    },err=>{
                        reject(err)
                    })
                }else{
                    handleArr(pro,index)
                }
            })
        })
    }
    race(pros){
        return new Promise(resolve,reject=>{
            pros.forEach(pro=>{
                if(pro instanceof MyPromise){
                    pro().then(res=>{
                        resolve(res)
                    },err=>{
                        reject(err)
                    })
                }else{
                    resolve(pro)
                }
            })
        })
    }
    allSettled(pros){
        return new Promise((resolve,reject)=>{
            const res = []
            let count = 0
            const addData = (status,value,i)=>{
                res[i] = {
                    status,
                    value
                }
                count++
                if(count == pros.length){
                    resolve(res)
                }
            }
            promise.forEach((pro,index)=>{
                if(pro instanceof MyPromise){
                    pro().then(res=>{
                        addData('fulfilled',res,index)
                    },err=>{
                        addData('rejected',err,index)
                    })
                }else{
                    addData('fulfilled',pro,index)
                }
            })
        })
    }
    any(pros){
        return new Promise((resolve,reject)=>{
            let cnt = 0
            pros.forEach(pro=>{
                if(pro instanceof MyPromise){
                    pro().then(res=>{
                        resolve(res)
                    },err=>{
                        cnt++
                        if(cnt===pros.length){
                            reject(new AggregateError("All Promises were rejected"))
                        }
                    })
                }
            })
        })
    }
}

const test1 = new MyPromise(resolve=>{
    resolve("成功")
})
console.log(test1)

const test2 = new MyPromise(reject=>{
    reject("失败")
})
console.log(test2)

const test3 = new MyPromise((resolve,reject)=>{
    resolve("成功")
    reject("失败")
})
console.log(test3)

cnst test4 = new MyPromise(resolve=>{
    resolve("成功")
}).then(res=>{
    console.log(res)
})