手写Promise

发布时间:2023年12月28日

目录

前言

状态

使用方法

构造函数

对象

结论

第一阶段

搭建基本结构

思路

代码实现

测试一下

实现then方法获取异步值

思路

改造代码如下

测试一下

成功场景

?失败场景

实现类的resolve,reject以及catch方法

思路

代码实现

测试一下

第一阶段总结

第二阶段

try catch错误处理机制

思路

代码实现

测试一下

then方法完善

思路

代码实现(全部代码)

测试一下

异步值是promise

异步值是普通值

链式调用

总结

第三阶段

完善类的resolve和reject

思路

代码实现

测试一下

实现all方法

思路

代码实现

测试一下

总结

心得体会

附上全部代码


前言

promise对于前端的重要性是毋庸置疑的,自己也在之前写过一篇promise的使用:

promise的使用和实例方法-CSDN博客

首先思考一个问题:promise的关键要素有什么?

这里我认为有两个关键点:1.promise的状态2.promise的使用方法

状态

promise的状态有三个:pending,fulfilled,rejected

而且只能由pending转化为其他两个,并且转化之后就无法在变化

使用方法

promise有两种使用方法:构造函数和对象

构造函数

将promise当做构造函数使用,让实例对象调用then,catch,finally等方法去获取异步值

let pro =  new myPromise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('王惊涛')
        // reject('失败了')
    },1000)

pro.then(res=>{
  console.log(res,'成功的值')
},rej=>{
  console.log(rej,'失败的值')
})
pro.catch(err=>{
  console.log(err,'错误的原因')
})
对象

对象直接可以调用resolve,reject,all,race等方法

Promise.resolve('王惊涛').then(res=>{
  console.log(res,'成功的值')
})

结论

Promise既可以作为函数,也可以作为对象,所以我们需要创建的是一个函数对象。

准确的说:一个用于静态方法和属性的构造函数

第一阶段

搭建基本结构

思路

1.创建一个构造函数或者类,这里我就直接用class类了

2.类里面有一个status属性,用来表示Promise的状态,成功和失败都会改变pending状态,并且不会再发生变化

3.promise作为构造函数,接受的参数是一个函数,所以:constructor接受一个函数。并且这个函数的两个参数也都是函数:resolve和reject方法,用来调用成功或者失败的值(这里为了区分,我就是用resolveFun和rejectFun)

4.new Promise的实例对象可以使用then和catch方法对异步值进行成功或者失败的操作

5.成功和失败都是需要回调函数去操作的,所以需要集合保存回调函数

6.promise本身作为对象可以调用resolve,reject,all等方法,这里需要设置静态方法,可以让类直接使用

代码实现

class myPromise{
    //new myPromise((res,rej)=>{res('成功')})
    //new myPromise((res,rej)=>{rej('失败')})
    constructor(proFun){  
    //这里的proFun就是:(res,rej)=>{res('成功')
       proFun(this.resolveFun,this.rejectFun) 
    }
    status = 'pengding' //状态
    resolveValue = null  //成功的值
    rejectReason = null  //失败的值
    successCallBackList = []  //成功回调集合
    failCallBackList = []   //失败回调集合
     
    //resolve处理函数
    resolveFun = (value)=>{
       console.log(value,'成功的值')
       this.status = 'fulfilled'  //改变状态为成功
       this.resolveValue = value  //赋值成功值
    }

    //reject处理函数
    rejectFun = (reason)=>{
        console.log(reason,'失败的值')
        this.status = 'rejected'  //改变状态为成功
        this.rejectReason = reason  //赋值成功值
    }

    //then实例方法
    thenFun = ()=>{
        console.log('测试then方法是否可以使用')
    }
    //catch实例方法
    catchFun = ()=>{

    }
    
    //promise直接调用resolve方法:myPromise.resolve('成功')
    static resolve = ()=>{
         console.log('测试resolve对象方法是否可用')
    }
    //promise直接调用reject方法:myPromise.reject('失败')
    static reject = ()=>{

    }
    //promise直接调用all方法:myPromise.all[pro1,pro2]
    static all = ()=>{

    }
}

测试一下

        //测试
        let pro = new myPromise(res => {
            setTimeout(() => {
                res('成功')
            }, 1000)
        })
        pro.thenFun(res => {
        })

        myPromise.resolve('成功')

实现then方法获取异步值

then方法无疑是promise核心的代码,因为then里面封装的是获取异步之后的回调逻辑。

我们在调用了resolveFun之后,会改变状态,并且把给value赋值,然后最关键的就是需要调用then方法中定义的函数

思路

1.then方法接收两个参数,并且这两个参数都是函数,一个用来处理成功后的逻辑,一个用来处理失败后的逻辑

2.两个函数的参数分别对应resolveValue和rejectReason的结果值

3.这个时候我们就应该将成功和失败的回调函数作为参数保存到我们在类中定义successCallback和failCallback这两个数组中

4.然后调用数组中的回调函数,并且将value值作为thenFun中的函数参数,然后就可以在then调用之后,获取到异步的值了

改造代码如下

只修改这个三个方法.其余代码不变

            //resolve处理函数
            resolveFun = (value) => {
                console.log(value, '成功的值')
                this.status = 'fulfilled'  //改变状态为成功
                this.resolveValue = value  //赋值成功值
                console.log(this.successCallBackList, '成功的回调函数列表')
                this.successCallBackList[0](value)
            }

            //reject处理函数
            rejectFun = (reason) => {
                console.log(reason, '失败的值')
                this.status = 'rejected'  //改变状态为成功
                this.rejectReason = reason  //赋值成功值
                console.log(this.failCallBackList, '失败的回调函数列表')
                this.failCallBackList[0](reason)
            }

            //then实例方法
            thenFun = (resolveCallBack, rejectCallBack) => {
                // console.log('测试then方法是否可以使用')
                this.successCallBackList.push(resolveCallBack)
                this.failCallBackList.push(rejectCallBack)
            }

测试一下

成功场景
        //测试
        let pro = new myPromise((res, rej) => {
            setTimeout(() => {
                res('成功')
                // rej('失败')
            }, 1000)
        })
        pro.thenFun(res => {
            console.log(res, '成功后的操作逻辑')
        }, rej => {
            console.log(rej, '失败后的操作逻辑')
        })

?失败场景
        //测试
        let pro = new myPromise((res, rej) => {
            setTimeout(() => {
                // res('成功')
                rej('失败')
            }, 1000)
        })
        pro.thenFun(res => {
            console.log(res, '成功后的操作逻辑')
        }, rej => {
            console.log(rej, '失败后的操作逻辑')
        })

归纳一下这里究竟发生了什么,就用上面的失败为例:

1.定义一个pro变量,为new myPromise类的对象。参数为一个函数,函数有两个参数,参数1代表需要调用成功逻辑,参数2表示需要调用失败逻辑

2pro对象这个时候调用了thenFun方法,将thenFun中定义的两个回调函数分别push添加到类中的回调数组中,这里失败添加到failCallBackList

3.计时器异步任务在执行完毕之后,rej('失败')调用,就将'失败'这一个值赋值给了rejectReason,并且修改了状态值为rejected

4.执行failCallBackList数组中函数,当然了,这里就一个,就是thenFun方法中第二个函数,将rejectReason作为参数调用该函数

5.然后就在thenFun函数中获取到了异步的失败值

关键就在这里,这里懂了,其实后续的很多东西都能好理解了,这里要是不懂,就多看几遍

实现类的resolve,reject以及catch方法

promise是可以这样使用的

        Promise.resolve('成功').then(res=>{
            console.log(res,'成功的值')
        })
        Promise.reject('失败').catch(rej=>{
            console.log(rej,'失败的值')
        })

所以这里我们就需要实现myPromise类中的静态方法resolve和reject,以及处理reject的catch方法

思路

1.调用了resolve和reject之后,需要调用then方法,所以调用这两个方法之后,返回的一定是一个promise对象,因为只有promise对象才可以调用then方法

2.catch方法其实和then方法没有什么本质的区别,所以可以直接让catchFun调用then方法,只是传参不一样而已

3.需要处理successCallBackList和failCallBackList为空的错误,因为我们这次没有往数组里添加回调函数,successCallBackList[0]()就会报错

代码实现

    //resolve处理函数
     resolveFun = (value) => {
        console.log(value, '成功的值')
        this.status = 'fulfilled'  //改变状态为成功
        this.resolveValue = value  //赋值成功值
        console.log(this.successCallBackList, '成功的回调函数列表')
        //处理数组为空时报错
        if(this.successCallBackList.length>0){
            this.successCallBackList[0](value)
        }
        
    }

    //reject处理函数
    rejectFun = (reason) => {
        console.log(reason, '失败的值')
        this.status = 'rejected'  //改变状态为成功
        this.rejectReason = reason  //赋值成功值
        console.log(this.failCallBackList, '失败的回调函数列表')
        //处理数组为空时报错
        if(this.failCallBackList.length>0){
            this.failCallBackList[0](reason)
        }
        
    }

    //then实例方法
    thenFun = (resolveCallBack, rejectCallBack) => {
        // console.log('测试then方法是否可以使用')
        this.successCallBackList.push(resolveCallBack)
        this.failCallBackList.push(rejectCallBack)
    }
    //catch实例方法
    catchFun = (reason)=>{
        //拿到失败值直接给thenFun就可以了
        this.thenFun(null,reason)
    }
    
    //promise直接调用resolve方法:myPromise.resolve('成功').thenFun(...)
    static resolve = (value)=>{ 
    //完了需要调用thenFun方法,所以必然是返回一个promise对象,所以需要new myPromise
       return new myPromise(resolve=>resolve(value))  
    }
    //promise直接调用reject方法:myPromise.reject('失败').catchFun(...)
    static reject = (reason)=>{
        //resolve思路一致,返回promise对象
       return new myPromise(reject=>reject(reason))
    }

测试一下

        myPromise.resolve('成功').thenFun(res=>{
            console.log(res,'成功的值')
        })
        myPromise.reject('失败').catchFun(rej=>{
            console.log(rej,'失败的值')
        })

第一阶段总结

其实这一阶段的代码算是结束了,总结一下功能:

1.实现了Promise类的基本结构

2.可以实现基本的then和catch异步取值,(当前仅限于常规值类型)

3.可以实现resolve和reject静态方法的调用

当前总体代码如下

class myPromise{
    //new myPromise((res,rej)=>{res('成功')})
    //new myPromise((res,rej)=>{rej('失败')})
    constructor(proFun){  
    //这里的proFun就是:(res,rej)=>{res('成功')
        proFun(this.resolveFun,this.rejectFun)    
    }
    status = 'pengding' //状态
    resolveValue = null  //成功的值
    rejectReason = null  //失败的值
    successCallBackList = []  //成功回调集合
    failCallBackList = []   //失败回调集合
     
     //resolve处理函数
     resolveFun = (value) => {
        console.log(value, '成功的值')
        this.status = 'fulfilled'  //改变状态为成功
        this.resolveValue = value  //赋值成功值
        console.log(this.successCallBackList, '成功的回调函数列表')
        //处理数组为空时报错
        if(this.successCallBackList.length>0){
            this.successCallBackList[0](value)
        }
        
    }

    //reject处理函数
    rejectFun = (reason) => {
        console.log(reason, '失败的值')
        this.status = 'rejected'  //改变状态为成功
        this.rejectReason = reason  //赋值成功值
        console.log(this.failCallBackList, '失败的回调函数列表')
        //处理数组为空时报错
        if(this.failCallBackList.length>0){
            this.failCallBackList[0](reason)
        }
        
    }

    //then实例方法
    thenFun = (resolveCallBack, rejectCallBack) => {
        // console.log('测试then方法是否可以使用')
        this.successCallBackList.push(resolveCallBack)
        this.failCallBackList.push(rejectCallBack)
    }
    //catch实例方法
    catchFun = (reason)=>{
        //拿到失败值直接给thenFun就可以了
        this.thenFun(null,reason)
    }
    
    //promise直接调用resolve方法:myPromise.resolve('成功').thenFun(...)
    static resolve = (value)=>{ 
    //完了需要调用thenFun方法,所以必然是返回一个promise对象,所以需要new myPromise
       return new myPromise(resolve=>resolve(value))  
    }
    //promise直接调用reject方法:myPromise.reject('失败').catchFun(...)
    static reject = (reason)=>{
        //resolve思路一致,返回promise对象
       return new myPromise(reject=>reject(reason))
    }
    //promise直接调用all方法:myPromise.all[pro1,pro2]
    static all = ()=>{

    }
}

第二阶段

我们需要考虑当下几种情况:

1.处理预期之外的错误,如果使用者没有按照我们预期的一样传递参数,那么就应该有错误处理机制,这里就需要使用try catch语法

2.then方法还不完善,比如我们resolve并不是传递的常规的值,而是一个新的promise,这里就需要对resolve和reject的值进行多种情况处理

3.resolve和reject类方法需要考虑传入promise而非值类型的情况

try catch错误处理机制

思路

let pro = new myPromise((res,rej)=>{
   console.log(a.b)
})
pro.thenFun(res=>{
  console.log('成功')
},rej=>{
  console.log('失败')
})

这里很明显,a.b肯定会报错

但是我们不应该让这个错误去阻断后续的执行,并且希望promise能把这个错误保存下来,让then方法中获取这个回调函数的执行失败状态,就需要如下处理

给proFun添加try catch错误处理机制

代码实现

    constructor(proFun){  
    //这里的proFun就是:(res,rej)=>{res('成功')
    try{
        proFun(this.resolveFun,this.rejectFun)    
    }catch(err){
        this.rejectFun(err)
    }  
    }

测试一下

then方法完善

思路

promise可以这样使用

        //promise本身
        let pro1 = new Promise((res,rej)=>{
            setTimeout(()=>{
                res(Promise.resolve('成功'))
            },1000)
        })
        pro1.then(res=>{
            console.log(res,'Promise本身的成功值')
        })
        
        //自定义的myPromise
        let pro2 = new myPromise((res,rej)=>{
            setTimeout(()=>{
                res(Promise.resolve('成功'))
            },1000)
        })
        pro2.thenFun(res=>{
            console.log(res,'当前自定义myPromise的成功值')
        })

下面的是我们自定义myPromise的输出过程,由此可看,在如下的时候,我们获取的就是一个Promise

?所以后续执行,返回的自然也是一个promise

所以,then方法关键就在于如果获取的是新的promise,就需要对它进行一个处理

代码实现(全部代码)

因为这次改动会很大,所以我就把主要注释都写到代码里面了,以下是全部代码

class myPromise{
    //new myPromise((res,rej)=>{res('成功')})
    //new myPromise((res,rej)=>{rej('失败')})
    constructor(proFun){  
    //这里的proFun就是:(res,rej)=>{res('成功')
    try{
        proFun(this.resolveFun,this.rejectFun)    
    }catch(err){
        this.rejectFun(err)
    }  
    }
    status = 'pengding' //状态
    resolveValue = null  //成功的值
    rejectReason = null  //失败的值
    successCallBackList = []  //成功回调集合
    failCallBackList = []   //失败回调集合
     
     //resolve处理函数
     resolveFun = (value) => {
        if (this.status !== 'pengding') return
        this.status = 'fulfilled'  //改变状态为成功
        this.resolveValue = value  //赋值成功值
        //处理数组为空时报错
        if(this.successCallBackList.length>0){
            this.successCallBackList.shift()(this.resolveValue)
        }
        
    }

    //reject处理函数
    rejectFun = (reason) => {
        if (this.status !== 'pengding') return
        this.status = 'rejected'  //改变状态为成功
        this.rejectReason = reason  //赋值成功值
        //处理数组为空时报错
        if(this.failCallBackList.length>0){
            this.failCallBackList.shift()(this.rejectReason)
        }
        
    }

    //then实例方法
    thenFun = (resolveCallBack, rejectCallBack) => {
        //一般情况下,这里的两个参数都是res和rej的回调函数
        //如then(res=>{console.log(res,'成功值')},rej=>{console.log(rej,'失败值')})
        //如果这里我们没有定义res或者rej,这里就需要默认赋值一个函数,参数一成功回调,参数二失败回调抛出错误
        resolveCallBack = resolveCallBack || (value => this.resolveValue)
        rejectCallBack = rejectCallBack || (reason => {throw this.rejectReason})

        //then方法是需要判断你获取的值究竟是值还是一个新的promise,这里我们用myPromise包装一下
        let newPromise = new myPromise((res,rej)=>{
           //这里就需要判断promise的状态了
           switch(this.status){
            //状态未定
            case 'pengding':
                //当你使用thenFun方法了,并且状态为pengding时,就需要向回调列表中添加任务
                this.successCallBackList.push(()=>{
                    try{
                       this.globalFun(newPromise,resolveCallBack,this.resolveValue,res,rej)
                    }catch(err){
                       rej(err)
                    }
                })
                this.failCallBackList.push(()=>{
                    try{
                        this.globalFun(newPromise,rejectCallBack,this.rejectReason,res,rej)
                    }catch(err){
                       rej(err)
                    }
                })
            break
            //成功
            case 'fulfilled':
             setTimeout(()=>{
                try{
                    this.globalFun(newPromise,resolveCallBack,this.resolveValue,res,rej)
                 }catch(err){
                    rej(err)
                 }
             })
            break
            //失败
            case 'rejected':
                setTimeout(()=>{
                    try{
                        this.globalFun(newPromise,rejectCallBack,this.rejectReason,res,rej)
                    }catch(err){
                       rej(err)
                    }
                 })
            break
           }
        })
        return newPromise
    }

    //公共方法,这里是用来进行逻辑判断的,then方法遇到各种情况,都需要在这个公共方法里处理一下,然后再去执行自己应该做的事情
    /**
     * 
     * @param {*} newPromise new的一个promise,作为thenFun的返回值
     * @param {*} callBack 来自thenFun的定义,或者是resolve函数,或者是reject函数,总之这个参数就是根据状态调用的
     * @param {*} value resolveValue || rejectReason
     * @param {*} resCallBack new promise的成功回调
     * @param {*} rejCallBack new promise的失败回调
     * @returns 
     */
    globalFun(newPromise,callBack,value,resCallBack,rejCallBack){
        //如果callBackValue是一个promise对象,比如如下情况
        //pro.then(res=>{
        //  return new myPromise(resolve=>{
        //     resolve('成功')
        //  })
        //})

        //如果value的值是一个myPromise对象,就必须把它拆开来处理,利用递归在传递给globalFun,让globalFun里面的value是一个常规值
        if(value instanceof myPromise){
            //成功状态
        if(value.status === 'fulfilled'){
        this.globalFun(newPromise,callBack,value.resolveValue,resCallBack,rejCallBack)
        }else if(value.status === 'rejected'){
            //失败状态
        this.globalFun(newPromise,callBack,value.resolveValue,resCallBack,rejCallBack)
        }
        }else{
            //其实获取了具体的异步值,下面这行代码就是将异步值给返回出去了
            let callBackValue = callBack(value)
            //如果已经有值有状态了,就不需要再往下走了
            //这里的场景就是你异步操作又返回了一个promise的值
            if(callBackValue instanceof myPromise){
                //异步值还是promise对象,再返回去拿值去吧
                callBackValue.thenFun(resCallBack,rejCallBack)
             }else{  
                //如果不是promise对象,就使用成功回调
                if(this.resolveValue instanceof myPromise){
                    this.resolveValue.thenFun(res=>{
                        this.resolveValue = res
                        resCallBack(res)
                    },rej=>{
                        rejCallBack(rej)
                    })
                }else{
                    resCallBack(callBackValue)
                }
    
             }
        }

    }
    //catch实例方法
    catchFun = (reason)=>{
        //拿到失败值直接给thenFun就可以了
       return this.thenFun(null,reason)
    }
    
    //promise直接调用resolve方法:myPromise.resolve('成功').thenFun(...)
    static resolve = (value)=>{ 
    //完了需要调用thenFun方法,所以必然是返回一个promise对象,所以需要new myPromise
    return new myPromise(resolve=>resolve(value))  
    //promise直接调用reject方法:myPromise.reject('失败').catchFun(...)
    static reject = (reason)=>{
        //resolve思路一致,返回promise对象
       return new myPromise(reject=>reject(reason))
    }
    //promise直接调用all方法:myPromise.all[pro1,pro2]
    static all = ()=>{

    }
}

//测试

测试一下

异步值是promise
        let pro1 = new myPromise((res,rej)=>{
            setTimeout(()=>{
                res(myPromise.resolve('成功的promise=>值'))
                // res('成功')
            },3000)
        })
        pro1.thenFun(res=>{
            console.log(res,'当前自定义myPromise的成功值1')
        },rej=>{
            console.log(rej,'当前自定义myPromise的失败值2')
        })

        let pro2 = new myPromise((res,rej)=>{
            setTimeout(()=>{
                rej(myPromise.resolve('失败的promise=>值'))
                // res('成功')
            },5000)
        })
        pro2.thenFun(res=>{
            console.log(res,'当前自定义myPromise的成功值1')
        },rej=>{
            console.log(rej,'当前自定义myPromise的失败值2')
        })

异步值是普通值
        let pro1 = new myPromise((res,rej)=>{
            setTimeout(()=>{
                // res(myPromise.resolve('成功的promise=>值'))
                res('成功')
            },3000)
        })
        pro1.thenFun(res=>{
            console.log(res,'当前自定义myPromise的成功值1')
        },rej=>{
            console.log(rej,'当前自定义myPromise的失败值2')
        })

        let pro2 = new myPromise((res,rej)=>{
            setTimeout(()=>{
                // rej(myPromise.resolve('失败的promise=>值'))
                res('成功')
            },5000)
        })
        pro2.thenFun(res=>{
            console.log(res,'当前自定义myPromise的成功值1')
        },rej=>{
            console.log(rej,'当前自定义myPromise的失败值2')
        })

链式调用

先看一下内置Promise的效果

 //层层依赖形成执行链
        let pro = new Promise(res=>{
          setTimeout(()=>{
            res('初始化成功')
          })
        })
        pro.then(res => {
          return new Promise(resolve => {
              setTimeout(() => {
                  console.log(res,'第一层链')
                  resolve(res,'第一层返回成功值')
              }, 2000)

          })
      }).then(res => {
          return new Promise(resolve => {
              setTimeout(() => {
                  console.log(res,'第二层链')
                  resolve('第二层返回成功值')
              }, 2000)

          })
      }).then(res => {
          return new Promise(resolve => {
              setTimeout(() => {
                  console.log(res,'第三层链')
                  resolve('第三层返回成功值')
              }, 2000)

          })
      }).then(res=>{
        console.log(res,'最终的值')
      })

我们自己的

//自己的myPromise链式调用
let pro = new myPromise(res=>{
    setTimeout(()=>{
      res('初始化成功自定义的')
    })
  })
  pro.thenFun(res => {
    return new myPromise(resolve => {
        setTimeout(() => {
            console.log(res,'第一层链自定义的')
            resolve(res,'第一层返回成功值')
        }, 2000)

    })
}).thenFun(res => {
    return new myPromise(resolve => {
        setTimeout(() => {
            console.log(res,'第二层链自定义的')
            resolve('第二层返回成功值')
        }, 2000)

    })
}).thenFun(res => {
    return new myPromise(resolve => {
        setTimeout(() => {
            console.log(res,'第三层链自定义的')
            resolve('第三层返回成功值')
        }, 2000)

    },reject=>{
        
    })
}).thenFun(res=>{
  console.log(res,'最终的值自定义的')
})

总结

第二阶段是promise最绕的阶段,因为在这里函数套函数,递归等等,需要好好看。

之前看promise源码,就属then里面的处理是最复杂的

说真的,这里我其实我写的时候,也是不停地调试,才给整出来的。思路很关键,但更重要的还是动手去写,我这里在自己编写的阶段,至少打印了20个console.log。也是踩坑踩出来的。

多看,强化理解,多练!!!

第三阶段

这里我们其实已经不想写太多了,在写下去估计很多人也没耐心看了。

好吧,我承认,我这篇文章写的也是挺心累的,这是第二天了

第三阶段,我就把类的resolve和reject完善一下,并且把all方法的实现完成

完善类的resolve和reject

思路

1.Promise.resolve(value),这个value可以是一个常规的值,也可以是一个new Promise(...),这样的话我们就需要对这两种情况做分别处理

2.reject同理

代码实现

    static resolve = (value)=>{ 
    //完了需要调用thenFun方法,所以必然是返回一个promise对象,所以需要new myPromise
    //value是myPromise对象,就返回他
    if(value instanceof myPromise){
        return value
    }else{
    //value是普通值,就给包装成一个myPromise
        return new myPromise(resolve=>resolve(value))  
    }
    }
    //promise直接调用reject方法:myPromise.reject('失败').catchFun(...)
    static reject = (reason)=>{
    //和resolve思路一致
        if(reason instanceof myPromise){
            return reason
        }else{
            return new myPromise(reject=>reject(reason))
        }
    }

测试一下

let pro1 = new Promise(res=>{
    setTimeout(()=>{
        res('promise成功值')
    },2000)
})
Promise.resolve(pro1).then(res=>{
    console.log(res,'成功的值')
})

let pro2 = new myPromise(res=>{
    setTimeout(()=>{
        res('promise成功值')
    },1000)
})
myPromise.resolve(pro2).thenFun(res=>{
    console.log(res,'成功的值自定义的myPromise')
})

实现all方法

思路

思路很简答,对于数组中promise进行依次执行,用计数器思想,全部执行完毕返回结果

代码实现

注释我写好了,一看就懂

    static all = (proList)=>{
        console.log(proList,'liebiao')
       let resultList = []
       let num = 0
       return new myPromise((resolve,reject)=>{
         let pushResult = (key,value)=>{
            resultList[key] = value
            num++
            if(num === proList.length){
                resolve(resultList)
            }
         }
         proList.forEach((item,index)=>{
            if(item instanceof myPromise){
                console.log('是myPromise类型')
                item.thenFun(res =>{
                    console.log(res,'每次执行结果')
                  pushResult(index,res)
                },rej=>{
                    reject(rej)
                })
            }else{
                pushResult(index,item)
            }
         })
       })
    }

测试一下

let pro1 = new myPromise((res,rej)=>{
    setTimeout(()=>{
       res('成功1')
    },1000)
})
let pro2 = new myPromise((res,rej)=>{
    setTimeout(()=>{
       res('成功2')
    },2000)
})
let pro3 = new myPromise((res,rej)=>{
    setTimeout(()=>{
       res('成功3')
    },3000)
})
myPromise.all([pro1,pro2,pro3]).thenFun(res=>{
    console.log(res,'全部执行完毕的结果')
})

总结

没啥多说的,第三阶段的比较简单,我想只要第二阶段的then看明白了,应该没啥问题

心得体会

其实还有很多方法没有写,但是我感觉写到这里基本上对promise本身的理解也差不多太多了。

这篇文章是我从头到尾一字一字敲的,感觉还是付出了心血滴...

核心就在thenFun方法的实现上,then的实现你弄懂了,基本上就没啥大问题了。

感觉还行的给个点赞,收藏,关注吧!!!

附上全部代码

class myPromise{
    //new myPromise((res,rej)=>{res('成功')})
    //new myPromise((res,rej)=>{rej('失败')})
    constructor(proFun){  
    //这里的proFun就是:(res,rej)=>{res('成功')
    try{
        proFun(this.resolveFun,this.rejectFun)    
    }catch(err){
        this.rejectFun(err)
    }  
    }
    status = 'pengding' //状态
    resolveValue = null  //成功的值
    rejectReason = null  //失败的值
    successCallBackList = []  //成功回调集合
    failCallBackList = []   //失败回调集合
     
     //resolve处理函数
     resolveFun = (value) => {
        if (this.status !== 'pengding') return
        this.status = 'fulfilled'  //改变状态为成功
        this.resolveValue = value  //赋值成功值
        //处理数组为空时报错
        if(this.successCallBackList.length>0){
            this.successCallBackList.shift()(this.resolveValue)
        }
        
    }

    //reject处理函数
    rejectFun = (reason) => {
        if (this.status !== 'pengding') return
        this.status = 'rejected'  //改变状态为成功
        this.rejectReason = reason  //赋值成功值
        //处理数组为空时报错
        if(this.failCallBackList.length>0){
            this.failCallBackList.shift()(this.rejectReason)
        }
        
    }

    //then实例方法
    thenFun = (resolveCallBack, rejectCallBack) => {
        //一般情况下,这里的两个参数都是res和rej的回调函数
        //如then(res=>{console.log(res,'成功值')},rej=>{console.log(rej,'失败值')})
        //如果这里我们没有定义res或者rej,这里就需要默认赋值一个函数,参数一成功回调,参数二失败回调抛出错误
        resolveCallBack = resolveCallBack || (value => this.resolveValue)
        rejectCallBack = rejectCallBack || (reason => {throw this.rejectReason})

        //then方法是需要判断你获取的值究竟是值还是一个新的promise,这里我们用myPromise包装一下
        let newPromise = new myPromise((res,rej)=>{
           //这里就需要判断promise的状态了
           switch(this.status){
            //状态未定
            case 'pengding':
                //当你使用thenFun方法了,并且状态为pengding时,就需要向回调列表中添加任务
                this.successCallBackList.push(()=>{
                    try{
                       this.globalFun(newPromise,resolveCallBack,this.resolveValue,res,rej)
                    }catch(err){
                       rej(err)
                    }
                })
                this.failCallBackList.push(()=>{
                    try{
                        this.globalFun(newPromise,rejectCallBack,this.rejectReason,res,rej)
                    }catch(err){
                       rej(err)
                    }
                })
            break
            //成功
            case 'fulfilled':
             setTimeout(()=>{
                try{
                    this.globalFun(newPromise,resolveCallBack,this.resolveValue,res,rej)
                 }catch(err){
                    rej(err)
                 }
             })
            break
            //失败
            case 'rejected':
                setTimeout(()=>{
                    try{
                        this.globalFun(newPromise,rejectCallBack,this.rejectReason,res,rej)
                    }catch(err){
                       rej(err)
                    }
                 })
            break
           }
        })
        return newPromise
    }

    //公共方法,这里是用来进行逻辑判断的,then方法遇到各种情况,都需要在这个公共方法里处理一下,然后再去执行自己应该做的事情
    /**
     * 
     * @param {*} newPromise new的一个promise,作为thenFun的返回值
     * @param {*} callBack 来自thenFun的定义,或者是resolve函数,或者是reject函数,总之这个参数就是根据状态调用的
     * @param {*} value resolveValue || rejectReason
     * @param {*} resCallBack new promise的成功回调
     * @param {*} rejCallBack new promise的失败回调
     * @returns 
     */
    globalFun(newPromise,callBack,value,resCallBack,rejCallBack){
        //如果callBackValue是一个promise对象,比如如下情况
        //pro.then(res=>{
        //  return new myPromise(resolve=>{
        //     resolve('成功')
        //  })
        //})

        //如果value的值是一个myPromise对象,就必须把它拆开来处理,利用递归在传递给globalFun,让globalFun里面的value是一个常规值
        if(value instanceof myPromise){
            //成功状态
        if(value.status === 'fulfilled'){
        this.globalFun(newPromise,callBack,value.resolveValue,resCallBack,rejCallBack)
        }else if(value.status === 'rejected'){
            //失败状态
        this.globalFun(newPromise,callBack,value.resolveValue,resCallBack,rejCallBack)
        }
        }else{
            //其实获取了具体的异步值,下面这行代码就是将异步值给返回出去了
            let callBackValue = callBack(value)
            //如果已经有值有状态了,就不需要再往下走了
            //这里的场景就是你异步操作又返回了一个promise的值
            if(callBackValue instanceof myPromise){
                //异步值还是promise对象,再返回去拿值去吧
                callBackValue.thenFun(resCallBack,rejCallBack)
             }else{  
                //如果不是promise对象,就使用成功回调
                if(this.resolveValue instanceof myPromise){
                    this.resolveValue.thenFun(res=>{
                        this.resolveValue = res
                        resCallBack(res)
                    },rej=>{
                        rejCallBack(rej)
                    })
                }else{
                    resCallBack(callBackValue)
                }
    
             }
        }

    }
    //catch实例方法
    catchFun = (reason)=>{
        //拿到失败值直接给thenFun就可以了
       return this.thenFun(null,reason)
    }
    
    //promise直接调用resolve方法:myPromise.resolve('成功').thenFun(...)
    static resolve = (value)=>{ 
    //完了需要调用thenFun方法,所以必然是返回一个promise对象,所以需要new myPromise
    if(value instanceof myPromise){
        return value
    }else{
        return new myPromise(resolve=>resolve(value))  
    }
    }
    //promise直接调用reject方法:myPromise.reject('失败').catchFun(...)
    static reject = (reason)=>{
    //和resolve思路一致
        if(reason instanceof myPromise){
            return reason
        }else{
            return new myPromise(reject=>reject(reason))
        }
    }
    //promise直接调用all方法:myPromise.all[pro1,pro2]
    static all = (proList)=>{
        console.log(proList,'liebiao')
       let resultList = []
       let num = 0
       return new myPromise((resolve,reject)=>{
         let pushResult = (key,value)=>{
            resultList[key] = value
            num++
            if(num === proList.length){
                resolve(resultList)
            }
         }
         proList.forEach((item,index)=>{
            if(item instanceof myPromise){
                console.log('是myPromise类型')
                item.thenFun(res =>{
                    console.log(res,'每次执行结果')
                  pushResult(index,res)
                },rej=>{
                    reject(rej)
                })
            }else{
                pushResult(index,item)
            }
         })
       })
    }
}

//测试

文章来源:https://blog.csdn.net/m0_54741495/article/details/135249893
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。