Promise原理分析及源码实现

本篇代码写的不太好

请点击这里,查看更好的Promise实现代码

阉割版promise

阉割之处:
当使用new来创建一个promise对象并且resolve的参数是一个promise对象时,正宗的promise应该是这样:

let p1 = new Promise((resolve, reject) => {
    
    
    setTimeout(() => {
    
    
        resolve(123)
    }, 1000);
})
let p2 = new Promise((resolve, reject) => {
    
    
    resolve(p1)
})
p2.then(value => {
    
    console.log(value)})
// 输出 123

而我的promise的却是这样:

let p1 = new MyPromise((resolve, reject) => {
    
    
    setTimeout(() => {
    
    
        resolve(123)
    }, 1000);
})
let p2 = new MyPromise((resolve, reject) => {
    
    
    resolve(p1)
})
p2.then(value => {
    
    console.log(value)})
/* 输出 MyPromise {
  State: 'pending',
  result: null,
  resolveCallBackFuntions: [],
  rejectCallBackFuntions: []
} */

可以看出两者的差别:正宗的Promise会把p1的结果值作为p2的结果值,而我的MyPromise会直接把p1这个对象作为p2的结果值。
我想破了脑袋,也没想出来该如何实现这个功能。

MyPromise的实现

promise实际上就是一个异步变同步的过程,对于一个异步任务A和一个任务B,promise要实现的基本功能也是最重要的功能就是让A执行完成之后,把执行结果传给B,然后B再开始执行。
实现的方式:声明一个resolve函数,resolve函数的内容是执行B任务。把resolve函数作为一个参数进行传递,以致让异步任务A能够访问到这个resolve函数,然后在A任务结束的时候调用resolve函数,把A运行的结果作为参数。这样就实现了上面这个最基本且最重要的功能。

MyPromise源码:

构造函数中,大致流程是这样的:
对象内部有两个数组,存储要执行的回调。
当resolve或rejected执行时,会遍历数组,执行所有的回调。

then方法中,大致流程是这样的:
把两个参数添加到回调数组中。

还没写完。。。

MyPromise():

module.exports = MyPromise
function MyPromise(executor){
    
    
    this.State = 'pending'
    this.result = null
    this.resolveCallBackFuntions = []   //成功时要调用的回调
    this.rejectCallBackFuntions = []    //失败时要调用的回调
    const self = this //让self指向当前promise对象
    function resolve(data){
    
    
        //因为resolve不是通过promise对象来调用的,所以不能在函数内写this,需要用self来代替this
        if (self.State === 'pending') {
    
    
            self.State = 'fullfilled'
            self.result = data
            self.resolveCallBackFuntions.forEach(resolveCallBack => {
    
    
                resolveCallBack.ret(resolveCallBack(self.result)) 
                //resolveCallBack :value => {}回调,并得到返回值,
                //返回值作为ret的参数
            })
        }
        
    }
    function reject(data){
    
    
        if (self.State === 'pending') {
    
    
            self.State = 'rejected'
            self.result = data
            self.rejectCallBackFuntions.forEach(rejectCallBack => {
    
    
                rejectCallBack.ret(rejectCallBack(self.result))
            })
        }
    }
    try{
    
    
        executor(resolve, reject) //在对象生成时就立即执行excutor函数
        //executor的函数体由使用promise的人决定,传入的参数resolve和reject由Promise内部决定
    }
    catch(e){
    
    
        //捕捉throw出来的错误
        reject(e)
    }
}

MyPromise.prototype.then()

MyPromise.prototype.then = function(resolveCallBack, rejectCallBack){
    
    
    if(typeof resolveCallBack !== 'function' && typeof rejectCallBack !== 'function'){
    
    
        return this
    }
    const self = this 
    return new MyPromise((resolve, reject) => {
    
    
        if(typeof resolveCallBack === 'function'){
    
    
            if(self.State === 'fullfilled'){
    
    
                //如果原对象状态是fullfilled,那么立即执行resolveCallback,同步得到返回值,并把返回值作为参数调用ret
                ret(resolveCallBack(self.result))
            }
            else {
    
    
                resolveCallBack.ret = ret
                //这里的this指向new Promise(),所以必须用self来指向调用then的那个对象
                self.resolveCallBackFuntions.push(resolveCallBack)
                //then返回的promise对象结果值是resolveCallBack:value => { }的返回值,同时也将作为resolve的参数
                //现在的目的就是得到resolveCallBack运行后的返回值 当作resolve的参数,
                //但resolveCallBack不是立即执行的,它和调用then方法的promise对象中的resolve一起执行
                //所以我把这个ret和resolveCallBack一同传到上面的promise对象中的resolve里面
                //上面的promise对象中的resolve里面调用ret,ret调用resolve或reject
            }
        }
        if(typeof rejectCallBack === 'function'){
    
    
            if(self.State === 'rejected'){
    
    
                reject(rejectCallBack(self.result))
            }
            else {
    
    
                rejectCallBack.ret = ret
                self.rejectCallBackFuntions.push(rejectCallBack)
            }
            
        }
        function ret(retValue){
    
     
            //ret功能是处理返回值可能为MyPromise对象的情况
            //retValue是resolveCallBack或者rejectCallBack的return值
            //retValue作为then返回对象的结果值
            if(retValue instanceof MyPromise){
    
    
                
                retValue.then(  
                    //如果retvalue是MyPromise对象,那么把retValue的结果值作为then返回对象的结果值
                    //只能把retvalue脱掉一层
                    //如果retvalue的结果值还是MyPromise对象,那么寄,then返回的对象的结果值就只能是个promise了
                    value => {
    
    resolve(value)},  
                    reason => {
    
    reject(reason)}
                    //把retValue的结果值作为then返回的MyPromise的结果值
                )
            }
            else {
    
    
                resolve(retValue)
                //如果不是MyPromise对象,那就直接resolve了
            }
        }
    })
}

MyPromise.prototype.catch()

MyPromise.prototype.catch = function(rejectCallBack){
    
     
    //注意,只要是用到this的函数都不要写成箭头形式,否则this不会指向调用它的对象
    return this.then(undefined, rejectCallBack)
}

MyPromise.resolve()

MyPromise.resolve = x => {
    
    
    return new MyPromise((resolve, reject) => {
    
    
        if(x instanceof MyPromise){
    
    
            x.then(
                value => {
    
    resolve(value)}, 
                reason => {
    
    reject(reason)}
            )
        }
        else {
    
    
            resolve(x)
        }
    })
}

MyPromise.reject()

MyPromise.reject = x => {
    
    
    return new MyPromise((resolve, reject) => {
    
    
        reject(x)
    })
}

MyPromise.all()

MyPromise.all = function(myPromises){
    
    
    return new MyPromise((resolve, reject) => {
    
    
        let resultArr = []
        let resolveCnt = 0
        myPromises.forEach(myPromise => {
    
    
            myPromise.then(
                value => {
    
    
                    resolveCnt++
                    resultArr.push(value)
                    if(resolveCnt === myPromises.length){
    
    
                        resolve(resultArr)
                    }
                },
                reason =>{
    
    
                    reject(reason)
                }
            )
        })
    })
}

MyPromise.race()

MyPromise.race = function(myPromises){
    
    
    return new MyPromise((resolve, reject) => {
    
    
        myPromises.forEach(myPromise => {
    
    
            myPromise.then(
                value => {
    
    
                    resolve(value)
                },
                reason => {
    
    
                    reject(reason)
                }
            )
        })
    })
}

猜你喜欢

转载自blog.csdn.net/m0_52744273/article/details/124117012
今日推荐