es5的方式封装Promise


es5的方式封装Promise

关键点:
	1、时刻关注Promise的状态
	2、执行的resolve和reject时候分两种情况来判别
		同步执行
		异步执行
	3、then返回是一个Promise对象,我们要对返回值进行一个判断
	4、then之后执行不管是resolve还是rejecte,都是异步代码,都要放到异步队列中执行
	5、then后面默认是可以不写代码的(例如:p.then()),因此我们需要给resolve和rejecte一个默认的方法
	6、catch方法可以异常穿透的
	7、all和race方法都是可以直接调用的,因此需要在Promise对象上加方法,而不能在原型对象上加
	8、all和race方法需要考虑部分Promise对象可能需要等待时间,但是需要返回的数组值不能乱顺序,因此需要用数组下标固定死返回值的位置
        9、this的指向可能会发生问题,最好每次都保存一下this的值
function Promise(executor) {
    this.PromiseState = 'pending'
    this.PromiseResult = undefined
    this.callback = []
    const self = this

    // 成功时候的回调方法
    function resolve(data) {
        setTimeout(function (){
            try {
                //判断状态
                if (self.PromiseState !== 'pending') return;
                self.PromiseResult = data
                self.PromiseState = "fulfilled"

                //当执行异步任务时,状态值发生了修改
                self.callback.forEach(item=>{
                    try{
                        item.success(data)
                    } catch (e) {
                        reject(e)
                    }
                })
            }catch(e){
                reject(e)
            }
        })
    }
    // 失败时候的回调方法
    function reject(data) {
        setTimeout(function() {
            try{
                if (self.PromiseState !== 'pending') return;
                self.PromiseResult = data
                self.PromiseState = "rejected"
                //当执行异步任务时,状态值发生了修改
                self.callback.forEach(item=>{
                    item.failed(data)
                })
            }catch (e) {
                reject(e)
            }
        })
    }
    executor(resolve,reject)
}

Promise.prototype.then = function (success,failed) {
    const self = this
    if (typeof success !== "function") {
        success = value => value
    }
    if (typeof failed !== "function") {
        failed = (reason) => {
            throw reason
        }
    }
    // then 方法返回的结果应该是一个Promise对象
    return new Promise((resolve,reject)=>{
        // 封装判断逻辑
        function judge(type) {
            try {
                let result = type(self.PromiseResult)
                if (result instanceof Promise) {
                    if (result.PromiseState === "pending") {
                        self.PromiseResult = result
                    } else if (result.PromiseResult === "rejected") {
                        reject(result.PromiseResult)
                    } else {
                        resolve(result.PromiseResult)
                    }
                } else {
                    resolve(result)
                }
            }catch (e) {
                reject(e)
            }
        }
        // 同步方法
        if (this.PromiseState === 'fulfilled') {
            judge(success)
        }
        if (this.PromiseState === 'rejected') {
            judge(failed)
        }
        if (this.PromiseState === 'pending') {
            this.callback.push({
                success:function () {
                    judge(success)
                },
                failed:function () {
                    judge(failed)
                }
            })
        }
    })
}

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

// 封装resolve
Promise.resolve = function (value) {
    const self = this
    if (value instanceof Promise) {
        return value
    } else {
        return new Promise((resolve,reject)=>{
            resolve(value)
        })
    }
}

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

Promise.all = function (arrays) {
    let resultArr = []
    let count = 0
    return new Promise((resolve,reject)=> {
        for (let i=0;i {
                count++
                resultArr[i] = value
                if (count === arrays.length) {
                    resolve(resultArr)
                }
            },reason => {
                reject(reason)
            })
        }
    })
}

Promise.race = function (arrays) {
    return new Promise((resolve,reject)=> {
        arrays.forEach( item=> {
            item.then(value => {
                resolve(value)
            },reason => {
                reject(reason)
            })
        })
    })
}