Promise从入门开始手写

350 阅读19分钟

Promise认知

promise用于异步变成的一种方式,表示一种期约/约定。有自己的状态且状态唯一,一旦改变就不可在变。 可以用来解决回调地狱的问题,也可以结合async await来实现异步代码同步化操作。

基本使用

const promise = new Promise((resolve,reject)=>{
    resolve("成功");
    //reject("失败");
})

promise拥有自己的状态,代表一种约定,一旦状态改变这个约定就有了结果,即状态不能再次被改变。

关于状态的改变:需要使用resolve方法来改变promise状态为成功的状态,使用reject方法来改变promise状态为失败的状态。

Promise类接收一个函数参数,可以称它为执行器,他在创建Promise对象的时候就会被调用。

    /*
    1.定义一个MyPromise类
    2.该类有自己的状态 分别为初始化时,成功,失败,状态是固定的,可以使用定义常量的方式来定义。
    2.该类接收一个立即执行的执行器函数
    3.改执行器函数接收两个参数resolve与reject,这两个函数不是我们创建的,是promise自带的,所以我们要在promise里定义这两个函数
    4.调用resolve方法会改吧promise状态为成功,且promise状态只能在pending时被改变,且只能改变一次,所以要判断状态为pending时才改变状态
    */
    //定义状态常量
    const PENDING = 'pening'//初始化状态
    const FULFILLED = 'fulfilled'//成功的状态
    const REJECTED = 'rejected'//失败的状态
    class MyPromise{
        //创建时初始化状态为pending
        status = PENDING;
        constructor(executor){
            executor(this.resolve,this.reject)
        }
        //之所以写成箭头函数是因为this的指向。不清楚的可以运行一下下面的例子
        resolve = ()=>{
            //判断状态为初始状态才改变状态值
            if(this.status === PENDING){
                this.status = FULFILLED
            }
        }
        reject = ()=>{
            if(this.status === PENDING){
                this.status = REJECTED
            }
        }
    }
    const promise1 = new MyPromise((resolve,reject)=>{
        resolve()
    })
    console.log(promise1)

用箭头函数与不用箭头函数的比较,resolve用箭头函数写,reject用普通函数写,比较两者

    const PENDING = 'pening'//初始化状态
    const FULFILLED = 'fulfilled'//成功的状态
    const REJECTED = 'rejected'//失败的状态
    class MyPromise{
        //创建时初始化状态为pending
        status = PENDING;
        constructor(executor){
            executor(this.resolve,this.reject)
        }
        //之所以写成箭头函数是因为this的指向。不清楚的可以运行一下下面的例子
        resolve = ()=>{
            //判断状态为初始状态才改变状态值
            if(this.status === PENDING){
                this.status = FULFILLED
            }
        }
        reject = function{
            if(this.status === PENDING){
                this.status = REJECTED
            }
        }
    }
    const promise1 = new MyPromise((resolve,reject)=>{
        resolve()
    })
    console.log("箭头函数",promise1)
    const promise2 = new MyPromise((resolve,reject)=>{
        reject()
    })
    console.log("普通函数",promise1)

得到如下结果,正常打印箭头函数,普通函数会报错。因为是this的指向问题。箭头函数没有自身的this,它的this是他上层函数的this,且在创建时已经确定,如果是普通函数,他是this在调用的时候确定,而我们使用resolve和reject的时候是直接调用的他的this为undefined,所以会报错。

image.png

创建的promise对象的状态改变之后就会触发相应的then方法。

const promise = new Promise((resolve,reject)=>{
    resolve("成功");
    //reject("失败");
})
promise.then(value=>{
    console.log("成功的状态:",value)
},reason=>{
    console.log("失败的原因:",reason)
})

promise对象状态改变之后触发相应的then方法,也就是promise实例有then方法。这个方法接受两个外部传入的函数,来处理相应的成功/失败的逻辑。

    const PENDING = 'pening'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class MyPromise{
        status = PENDING;
        //初始化value与reason
        value = undefined;
        reason = undefined;
        constructor(executor){
            executor(this.resolve,this.reject)
        }
        resolve = (value)=>{
            if(this.status === PENDING){
                this.status = FULFILLED;
                //成功则改变value为传入的值
                this.value = value;
                
            }
        }
        reject = (reason)=>{
            if(this.status === PENDING){
                //失败则改变reason 为传入的值
                this.status = REJECTED;
                this.reason =reason;
            }
        }
        //为primose实例新增then方法,接受两个函数参数/分布来处理相应的成功/失败的逻辑。
        //必须在相应的状态执行相应的逻辑
        //成功的状态调用传入的第一个函数参数,此函数参数的参数为修改状态为成功时调用的resolve方法传入的参数this.value
        //失败的状态调用传入的第二个函数参数,此函数参数的参数为修改状态为失败时调用的reject方法传入的参数this.reason
        then = (fulfilled,rejected)=>{
            if(this.status === FULFILLED){
                fulfilled(this.value)
            }
            else if(this.status === REJECTED){
                rejected(this.reason)
            }
        }
    }
    const promise1 = new MyPromise((resolve,reject)=>{
        resolve()
    })
    promise1.then(value=>{
        console.log("成功状态:",value)
    },reason=>{
        console.log("失败状态:",reason)
    })
    

异步逻辑

JS代码的运行分为同步任务与异步任务。上面定义的myPromise运行同步代码是没有问题的,当创建一个新的promise对象时,直接改变了他的状态,在接下来使用此promise的then方法,此处状态已经改变,所以会按照他的状态执行接下来的流程。但是如果创建promise时改变promise状态的操作是异步的,如使用定时器在几秒之后再改变promise的状态,此时执行到then方法时,状态还是pending状态,而上面定义的myPromise并没有在状态为pending时的处理逻辑。所以我们应该为状态为pending时添加相应的处理逻辑。看下面的代码。

//沿用上面定义的MyPromise
const promise = new MyPromise((resolve,reject)=>{
    setTimeout(()=>{
        resolve("延迟2s改变状态")
    },2000)
})
promise.then(value=>{
    console.log(value)
},reason=>{
    console.log(reason)
})
/*
   创建了一个promise对象。执行器中有setTimeout会把定时器中的逻辑加入异步队列。
   继续执行promise对象的then方法,此时promise的状态为pending不会进行任何操作。
   同步代码执行完毕,检查异步对列,发现有一个,则在时间到达时执行异步逻辑,设置promise的状态为成功的状态。所以上面的代码不会有任何输出。
   
   经过上面的分析,问题出在执行then方法时,promise的状态还没有改变,所以不会进行任何操作。我们要做的就是,如果在执行then方法时promise的状态为pending,则把相应的逻辑存储起来,等到状态改变时执行相应的逻辑。
   
*/

修改MyPromise代码如下

    const PENDING = 'pening'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class MyPromise{
        status = PENDING;
        value = undefined;
        reason = undefined;
        //初始化then传入的成功时缓存的相关逻辑
        fulfilledCallback = undefined;
        //初始化then传入的失败时缓存的相关逻辑
        rejectedCallback = undefined;
        constructor(executor){
            executor(this.resolve,this.reject)
        }
        resolve = (value)=>{
            if(this.status === PENDING){
                this.status = FULFILLED;
                this.value = value;
                //状态改变为成功时时,如果有缓存的成功状态的相关逻辑,则执行
                this.fulfilledCallback && this.fulfilledCallback(this.value)
            }
        }
        reject = (reason)=>{
            if(this.status === PENDING){
                this.status = REJECTED;
                this.reason =reason;
                //状态改变为失败时,如果有缓存的失败状态的相关逻辑,则执行
                this.rejectedCallback && this.rejectedCallback(this.reason)
            }
        }
        then = (fulfilled,rejected)=>{
            if(this.status === FULFILLED){
                fulfilled(this.value)
            }
            else if(this.status === REJECTED){
                rejected(this.reason)
            }
            //如果状态为pending则存储then传入的执行逻辑
            else{
                this.fulfilledCallback = fulfilled;
                this.rejectedCallback =rejected;
            }
        }
    }
    const promise1 = new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("延迟2秒改变状态为成功")
        },2000)
    })
    promise1.then(value=>{
        console.log("成功状态:",value)
    },reason=>{
        console.log("失败状态:",reason)
    })

多次调用then方法

同一个promise对象是可以多次调用then方法的,不管调用多少次then方法,在状态已经改变的请求下。都会按照状态来执行相关逻辑。但是如果是异步逻辑,多次调用then方法时,promise状态还没有改变,按照我们上面的代码,直接对fulfilledCallback或者是rejectedCallback进行赋值的话,就只会执行最后一次的逻辑。而每一次then方法的逻辑都应该在状态改变之后执行,也就是说需要存储多个函数,并且在状态改变之后执行。改写myPromise代码如下。

    const PENDING = 'pening'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class MyPromise{
        status = PENDING;
        value = undefined;
        reason = undefined;
        //可能会有多个逻辑,所以改写为数组类型
        fulfilledCallback = [];
        rejectedCallback = [];
        constructor(executor){
            executor(this.resolve,this.reject)
        }
        resolve = (value)=>{
            if(this.status === PENDING){
                this.status = FULFILLED;
                this.value = value;
                //执行成功状态数组中的每一个函数,执行顺序为第一个先执行。
                while(this.fulfilledCallback.length){
                    //用shift方法从最前面开始取函数执行
                    this.fulfilledCallback.shift()(this.value)
                }
            }
        }
        reject = (reason)=>{
            if(this.status === PENDING){
                this.status = REJECTED;
                this.reason =reason;
                 //执行失败状态数组中的每一个函数,执行顺序为第一个先执行。
                while(this.rejectedCallback.length){
                    //用shift方法从最前面开始取函数执行
                    this.rejectedCallback.shift()(this.reason)
                }
            }
        }
        then = (fulfilled,rejected)=>{
            if(this.status === FULFILLED){
                fulfilled(this.value)
            }
            else if(this.status === REJECTED){
                rejected(this.reason)
            }
            //如果状态为pending则给相关数组加入相关函数
            else{
                this.fulfilledCallback.push(fulfilled);
                this.rejectedCallback.push(rejected);
            }
        }
    }
    const promise1 = new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("延迟2秒改变状态为成功")
        },2000)
    })
    promise1.then(value=>{
        console.log("成功状态1:",value)
    },reason=>{
        console.log("失败状态1:",reason)
    })
    promise1.then(value=>{
        console.log("成功状态2:",value)
    },reason=>{
        console.log("失败状态2:",reason)
    })
    promise1.then(value=>{
        console.log("成功状态3:",value)
    },reason=>{
        console.log("失败状态3:",reason)
    })

then方法的链式调用

then方法可以链式调用,链式调用的基本使用

const promise = new Promise((resolve,reject)=>{
    resolve("第一次链式调用")
})
promise.then(value=>{
    console.log(value)
    return "第二次链式调用"
}).then(value=>{
    console.log(value)
})
//打印第一次链式调用
//第二次链式调用

从上面代码可以看出,then可以进行链式调用,那么then应该返回一个promise对象。且该promise对象的then方法传入的成功的回调与失败的回调的参数是上一个then方法的返回值。

    const PENDING = 'pening'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class MyPromise{
        status = PENDING;
        value = undefined;
        reason = undefined;
        fulfilledCallback = [];
        rejectedCallback = [];
        constructor(executor){
            executor(this.resolve,this.reject)
        }
        resolve = (value)=>{
            if(this.status === PENDING){
                this.status = FULFILLED;
                this.value = value;
                while(this.fulfilledCallback.length){
                    this.fulfilledCallback.shift()(this.value)
                }
            }
        }
        reject = (reason)=>{
            if(this.status === PENDING){
                this.status = REJECTED;
                this.reason =reason;
                while(this.rejectedCallback.length){
                    this.rejectedCallback.shift()(this.reason)
                }
            }
        }
        then = (fulfilled,rejected)=>{
            //then方法需要返回一个promise对象
            const promise2 = new MyPromise((resolve,reject)=>{
                 if(this.status === FULFILLED){
                     //接受返回值,作为下一次then的参数
                    const x = fulfilled(this.value)
                    resolve(x)
                }
                else if(this.status === REJECTED){
                    rejected(this.reason)
                }
                else{
                    this.fulfilledCallback.push(fulfilled);
                    this.rejectedCallback.push(rejected);
                }
            })
           
            return promise2
        }
    }
    const promise1 = new MyPromise((resolve,reject)=>{
        resolve("第一次链式调用")
    })
    promise1.then(value=>{
        console.log(value)
        return "第二次链式调用"
    }).then(value=>{
        console.log(value)
    })

then方法不止可以返回普通的数据,还可能返回promise对象,更加返回类型不同需要做不同的处理,如果返回的是一个普通的值,则直接调用resolve方法,传递返回值即可。如果是promise对象则要根据promise对象的状态来确定是调用resolve还是reject方法。

    const PENDING = 'pening'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class MyPromise{
        status = PENDING;
        value = undefined;
        reason = undefined;
        fulfilledCallback = [];
        rejectedCallback = [];
        constructor(executor){
            executor(this.resolve,this.reject)
        }
        resolve = (value)=>{
            if(this.status === PENDING){
                this.status = FULFILLED;
                this.value = value;
                while(this.fulfilledCallback.length){
                    this.fulfilledCallback.shift()(this.value)
                }
            }
        }
        reject = (reason)=>{
            if(this.status === PENDING){
                this.status = REJECTED;
                this.reason =reason;
                while(this.rejectedCallback.length){
                    this.rejectedCallback.shift()(this.reason)
                }
            }
        }
        then = (fulfilled,rejected)=>{
            //then方法需要返回一个promise对象
            const promise2 = new MyPromise((resolve,reject)=>{
                 if(this.status === FULFILLED){
                     //接受返回值,作为下一次then的参数
                    const x = fulfilled(this.value)
                    //判断返回值类型做不同的处理,多个地方要使用,所以封装成一个函数
                    resolvePromise(x,resolve,reject)
                }
                else if(this.status === REJECTED){
                    rejected(this.reason)
                }
                else{
                    this.fulfilledCallback.push(fulfilled);
                    this.rejectedCallback.push(rejected);
                }
            })
           
            return promise2
        }
    }
    function resolvePromise(x,resolve,reject){
        //判断x的值,如果是普通值则直接resolve,promise类型的值则根据promise状态确定调用哪个方法
        if(x instanceof MyPromise){
            x.then(value=>resolve(value),reason=>reject(reason))
        }
        else{
            resolve(x)
        }
    }
    const promise1 = new MyPromise((resolve,reject)=>{
        resolve("第一次链式调用")
    })
    promise1.then(value=>{
        console.log(value)
        return new MyPromise((resolve,reject)=>{
            resolve("返回一个promsie对象")
        })
    }).then(value=>{
        console.log(value)
    })

then方法返回的promise对象不能是他执行完毕之后返回的promise对象,否则会发生循环引用。

  const promise = new Promise((resolve,reject)=>{
        resolve("第一次调用")
    })
  const promise1 = promise.then(value=>{
        console.log(value)
        return promise1
    })
    //第一次调用
    // UnhandledPromiseRejectionWarning: TypeError: Chaining cycle detected for promise #<Promise>

像上面这样就会出现循环引用报错。改写MyPromise

    const PENDING = 'pening'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class MyPromise{
        status = PENDING;
        value = undefined;
        reason = undefined;
        fulfilledCallback = [];
        rejectedCallback = [];
        constructor(executor){
            executor(this.resolve,this.reject)
        }
        resolve = (value)=>{
            if(this.status === PENDING){
                this.status = FULFILLED;
                this.value = value;
                while(this.fulfilledCallback.length){
                    this.fulfilledCallback.shift()(this.value)
                }
            }
        }
        reject = (reason)=>{
            if(this.status === PENDING){
                this.status = REJECTED;
                this.reason =reason;
                while(this.rejectedCallback.length){
                    this.rejectedCallback.shift()(this.reason)
                }
            }
        }
        then = (fulfilled,rejected)=>{
            const promise2 = new MyPromise((resolve,reject)=>{
                 if(this.status === FULFILLED){
                    //需要判断promise2与x是不是同一个对象,同一对象则会循环引用
                    //promise2会在函数执行完毕之后才会创建,要想在这里使用,需要使用异步任务
                    setTimeout(()=>{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,reslove,reject)
                    },0)
                }
                else if(this.status === REJECTED){
                    rejected(this.reason)
                }
                else{
                    this.fulfilledCallback.push(fulfilled);
                    this.rejectedCallback.push(rejected);
                }
            })
           
            return promise2
        }
    }
    function resolvePromise(promise2,x,resolve,reject){
        //相同则reject给一个类型错误信息
        if(promise2 === x){
           return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
        }
        if(x instanceof MyPromise){
            x.then(value=>resolve(value),reason=>reject(reason))
        }
        else{
            resolve(x)
        }
    }
const promise1 = new MyPromise((resolve,reject)=>{
    resolve("第一次链式调用")
})
const promise2 = promise1.then(value=>{
    console.log(value)
    return promise2
})
promise2.then(value=>{},reason=>{
    console.log(reason)
})

错误处理及失败状态代码补全

在代码执行过程中,是可能会发生错误的,当错误出现的时候我们要捕获这个错误,并且把promise的状态设置为reject。

可能发生错误的地方有执行器执行的时候,then方法调用的时候。

    const PENDING = 'pening'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class MyPromise{
        status = PENDING;
        value = undefined;
        reason = undefined;
        fulfilledCallback = [];
        rejectedCallback = [];
        constructor(executor){
            //如果执行器出现错误,则改变状态为reject
            try{
                executor(this.resolve,this.reject)
            }
            catch(err){
                this.reject(err)
            }
            
        }
        resolve = (value)=>{
            if(this.status === PENDING){
                this.status = FULFILLED;
                this.value = value;
                while(this.fulfilledCallback.length){
                    //下面改写之后传递了参数,这里不用再传
                    this.fulfilledCallback.shift()()
                }
            }
        }
        reject = (reason)=>{
            if(this.status === PENDING){
                this.status = REJECTED;
                this.reason =reason;
                while(this.rejectedCallback.length){
                    //下面改写之后传递了参数,这里不用再传
                    this.rejectedCallback.shift()()
                }
            }
        }
        then = (fulfilled,rejected)=>{
            const promise2 = new MyPromise((resolve,reject)=>{
                 if(this.status === FULFILLED){
                    //需要判断promise2与x是不是同一个对象,同一对象则会循环引用
                    //promise2会在函数执行完毕之后才会创建,要想在这里使用,需要使用异步任务
                    setTimeout(()=>{
                        //执行fulfilled时出现错误也要吧状态改为reject,给后面的then使用
                        try{
                            const x = fulfilled(this.value)
                            resolvePromise(promise2,x,resolve,reject)
                        }
                        catch(err){
                            reject(err)
                        } 
                    },0)
                }
                else if(this.status === REJECTED){
                    //参照成功状态补全失败状态代码
                    //需要判断promise2与x是不是同一个对象,同一对象则会循环引用
                    //promise2会在函数执行完毕之后才会创建,要想在这里使用,需要使用异步任务
                    setTimeout(()=>{
                        //执行fulfilled时出现错误也要吧状态改为reject,给后面的then使用
                        try{
                            const x = rejected(this.reason)
                            resolvePromise(promise2,x,resolve,reject)
                        }
                        catch(err){
                            reject(err)
                        } 
                    },0)
                }
                else{
                    //参照成功状态进行改下存储的函数
                    this.fulfilledCallback.push(()=>{
                          setTimeout(()=>{
                        //执行fulfilled时出现错误也要吧状态改为reject,给后面的then使用
                        try{
                            const x = fulfilled(this.value)
                            resolvePromise(promise2,x,resolve,reject)
                        }
                        catch(err){
                            reject(err)
                        } 
                    },0)
                    })
                    this.rejectedCallback.push(()=>{
                         setTimeout(()=>{
                        //执行fulfilled时出现错误也要吧状态改为reject,给后面的then使用
                        try{
                            const x = rejected(this.reason)
                            resolvePromise(promise2,x,resolve,reject)
                        }
                        catch(err){
                            reject(err)
                        } 
                    },0)
                    });
                }
            })
           
            return promise2
        }
    }
    function resolvePromise(promise2,x,resolve,reject){
        if(promise2 === x){
           return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
        }
        if(x instanceof MyPromise){
            x.then(value=>resolve(value),reason=>reject(reason))
        }
        else{
            resolve(x)
        }
    }
const promise1 = new MyPromise((resolve,reject)=>{
 setTimeout(() => {
     resolve("成功")
 }, 2000);
})
promise1.then(value=>{
    console.log(value)
    return "返回一个普通值"
}).then(value=>{
    console.log(value)
})

将then方法参数变为可选参数

promise中如果then方法没有传参,那么他的状态是可以原样向后传递的,如

const promise = new Promise(resolve,reject=>{
    reject("成功")
})
promise.then().then().then(value=>{
    console.log(value)
})
//最后会打印成功
//等同于下面的代码
promise.then(value=>value).then(value=>value).then(value=>{
    console.log(value)
})

判断then方法参数是否存在

    const PENDING = 'pening'
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    class MyPromise{
        status = PENDING;
        value = undefined;
        reason = undefined;
        fulfilledCallback = [];
        rejectedCallback = [];
        constructor(executor){
            //如果执行器出现错误,则改变状态为reject
            try{
                executor(this.resolve,this.reject)
            }
            catch(err){
                this.reject(err)
            }
            
        }
        resolve = (value)=>{
            if(this.status === PENDING){
                this.status = FULFILLED;
                this.value = value;
                while(this.fulfilledCallback.length){
                    //下面改写之后传递了参数,这里不用再传
                    this.fulfilledCallback.shift()()
                }
            }
        }
        reject = (reason)=>{
            if(this.status === PENDING){
                this.status = REJECTED;
                this.reason =reason;
                while(this.rejectedCallback.length){
                    //下面改写之后传递了参数,这里不用再传
                    this.rejectedCallback.shift()()
                }
            }
        }
        then = (fulfilled,rejected)=>{
            //需要判断fulfilled与rejected是否存在,存在则进行之前的逻辑,不存在的话给他一个默认函数
            fulfilled = fulfilled ? fulfilled :value=>value;
            //用throw才能改变状态为失败。用来传递错误
            rejected = rejected ? rejected :reason=>{throw reason};
            const promise2 = new MyPromise((resolve,reject)=>{
                 if(this.status === FULFILLED){
                    setTimeout(()=>{
                        try{
                            const x = fulfilled(this.value)
                            resolvePromise(promise2,x,resolve,reject)
                        }
                        catch(err){
                            reject(err)
                        } 
                    },0)
                }
                else if(this.status === REJECTED){
                    setTimeout(()=>{
                        try{
                            const x = rejected(this.reason)
                            resolvePromise(promise2,x,resolve,reject)
                        }
                        catch(err){
                            reject(err)
                        } 
                    },0)
                }
                else{
                    this.fulfilledCallback.push(()=>{
                          setTimeout(()=>{
                        try{
                            const x = fulfilled(this.value)
                            resolvePromise(promise2,x,resolve,reject)
                        }
                        catch(err){
                            reject(err)
                        } 
                    },0)
                    })
                    this.rejectedCallback.push(()=>{
                         setTimeout(()=>{
                        try{
                            const x = rejected(this.reason)
                            resolvePromise(promise2,x,resolve,reject)
                        }
                        catch(err){
                            reject(err)
                        } 
                    },0)
                    });
                }
            })
           
            return promise2
        }
    }
    function resolvePromise(promise2,x,resolve,reject){
        if(promise2 === x){
           return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
        }
        if(x instanceof MyPromise){
            x.then(value=>resolve(value),reason=>reject(reason))
        }
        else{
            resolve(x)
        }
    }
const promise1 = new MyPromise((resolve,reject)=>{
 resolve("成功")
})
promise1.then().then().then(value=>{
    console.log(value)
})

Promise.all

Promise.all可以同时执行多个promise,返回一个promise对象,只有当所有的promise的状态为成功的状态,他的状态才为成功,接受到的成功的数据为一个数组,结果数组顺序和传入promise的顺序一致,有一个失败则为失败的状态,且失败的原因为失败的promise的原因。

const PENDING = 'pening'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
    status = PENDING;
    value = undefined;
    reason = undefined;
    fulfilledCallback = [];
    rejectedCallback = [];
    //all通过类名直接调用,所以他是一个静态方法,接受一个数组,数组元素可以使普通数据也可以是promise对象
    static all(arr){
        //定义一个结果数组来存储获得数据
        return new MyPromise((resolve,reject)=>{
            let result = [];
            //如果遇到异步任务,forEach会先执行完毕,如果直接resolve的话,会造成异步任务结果为空,只有等待所有promise都拿到了结果且放进result数组之后才能进行resolve。定义一个变量来检查是否全部添加完成。
            let resultIndex = 0;
            //遍历拿到所有的数组元素
            arr.forEach((item,index)=>{
            //如果是普通数据,则直接得到这个数据,如果是promise对象则要根据对象状态来确定操作
                if(item instanceof MyPromise){
                    //成功状态把成功的值给结果数组,失败则状态改变为失败,传递失败的原因
                    item.then(value=>{
                        result[index] = value;
                        resultIndex++;
                        //已添加的数量等于传入的数量时才改变状态
                        if(resultIndex === arr.length){
                            resolve(result)
                        }  
                    },reason=>reject(reason))
                }
                else{
                    result[index] = item;
                    resultIndex++;
                    //已添加的数量等于传入的数量时才改变状态
                    if(resultIndex === arr.length){
                        resolve(result)
                    }  
                }
               
            })
        })
      
    }
    constructor(executor){
        try{
            executor(this.resolve,this.reject)
        }
        catch(err){
            this.reject(err)
        }
    }
    resolve = (value)=>{
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
            while(this.fulfilledCallback.length){
                this.fulfilledCallback.shift()()
            }
        }
    }
    reject = (reason)=>{
        if(this.status === PENDING){
            this.status = REJECTED;
            this.reason =reason;
            while(this.rejectedCallback.length){
                this.rejectedCallback.shift()()
            }
        }
    }
    then = (fulfilled,rejected)=>{
        fulfilled = fulfilled ? fulfilled :value=>value;
        rejected = rejected ? rejected :reason=>{throw reason};
        const promise2 = new MyPromise((resolve,reject)=>{
             if(this.status === FULFILLED){
                setTimeout(()=>{
                    try{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
            }
            else if(this.status === REJECTED){
                setTimeout(()=>{
                    try{
                        const x = rejected(this.reason)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
            }
            else{
                this.fulfilledCallback.push(()=>{
                      setTimeout(()=>{
                    try{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
                })
                this.rejectedCallback.push(()=>{
                     setTimeout(()=>{
                    try{
                        const x = rejected(this.reason)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
                });
            }
        })
       
        return promise2
    }
}
function resolvePromise(promise2,x,resolve,reject){
    if(promise2 === x){
       return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
    }
    if(x instanceof MyPromise){
        x.then(value=>resolve(value),reason=>reject(reason))
    }
    else{
        resolve(x)
    }
}
function p1(){
    return new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('p1')
        },2000)
    })
}
function p2(){
    return new MyPromise((resolve,reject)=>{
        resolve('p2')
    })
}
MyPromise.all(['a','b',p1(),p2(),'c']).then(value=>{
    console.log(value)
})

Promise.resolve

Promise.resolve会将接受到的数字转换为一个promise对象返回,如果传入的就是一个promise对象则会原封不动的返回

const PENDING = 'pening'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
    status = PENDING;
    value = undefined;
    reason = undefined;
    fulfilledCallback = [];
    rejectedCallback = [];
    static resolve(value){
        //判断data的类型,如果是promise类型的则原封不动的返回
        if(value instanceof MyPromise){
            return value
        }
        //如果是普通类型的则转换为promise对象返回
        else{
            return new MyPromise((resolve,reject)=>{
                resolve(value)
            })
        }
    }
    static all(arr){
        return new MyPromise((resolve,reject)=>{
            let result = [];
            let resultIndex = 0;
            arr.forEach((item,index)=>{
                if(item instanceof MyPromise){
                    item.then(value=>{
                        result[index] = value;
                        resultIndex++;
                        if(resultIndex === arr.length){
                            resolve(result)
                        }  
                    },reason=>reject(reason))
                }
                else{
                    result[index] = item;
                    resultIndex++;
                    if(resultIndex === arr.length){
                        resolve(result)
                    }  
                }
               
            })
        })
      
    }
    constructor(executor){
        try{
            executor(this.resolve,this.reject)
        }
        catch(err){
            this.reject(err)
        }
    }
    resolve = (value)=>{
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
            while(this.fulfilledCallback.length){
                this.fulfilledCallback.shift()()
            }
        }
    }
    reject = (reason)=>{
        if(this.status === PENDING){
            this.status = REJECTED;
            this.reason =reason;
            while(this.rejectedCallback.length){
                this.rejectedCallback.shift()()
            }
        }
    }
    then = (fulfilled,rejected)=>{
        fulfilled = fulfilled ? fulfilled :value=>value;
        rejected = rejected ? rejected :reason=>{throw reason};
        const promise2 = new MyPromise((resolve,reject)=>{
             if(this.status === FULFILLED){
                setTimeout(()=>{
                    try{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
            }
            else if(this.status === REJECTED){
                setTimeout(()=>{
                    try{
                        const x = rejected(this.reason)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
            }
            else{
                this.fulfilledCallback.push(()=>{
                      setTimeout(()=>{
                    try{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
                })
                this.rejectedCallback.push(()=>{
                     setTimeout(()=>{
                    try{
                        const x = rejected(this.reason)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
                });
            }
        })
       
        return promise2
    }
}
function resolvePromise(promise2,x,resolve,reject){
    if(promise2 === x){
       return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
    }
    if(x instanceof MyPromise){
        x.then(value=>resolve(value),reason=>reject(reason))
    }
    else{
        resolve(x)
    }
}
function p1(){
    return new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('p1')
        },2000)

    })
}
function p2(){
    return new MyPromise((resolve,reject)=>{
        resolve('p2')
    })
}
MyPromise.resolve('a').then(value=>{
    console.log(value)
})
MyPromise.resolve(p1()).then(value=>{
    console.log(value)
})

finally方法

无论promise的状态如何finally中的代码都会执行,他接受一个函数参数。返回一个promise对象。

const PENDING = 'pening'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
    status = PENDING;
    value = undefined;
    reason = undefined;
    fulfilledCallback = [];
    rejectedCallback = [];
    static resolve(data){
        //判断data的类型,如果是promise类型的则原封不动的返回
        if(data instanceof MyPromise){
            return data
        }
        //如果是普通类型的则转换为promise对象返回
        else{
            return new MyPromise((resolve,reject)=>{
                resolve(data)
            })
        }
    }
    static all(arr){
        return new MyPromise((resolve,reject)=>{
            let result = [];
            let resultIndex = 0;
            arr.forEach((item,index)=>{
                if(item instanceof MyPromise){
                    item.then(value=>{
                        result[index] = value;
                        resultIndex++;
                        if(resultIndex === arr.length){
                            resolve(result)
                        }  
                    },reason=>reject(reason))
                }
                else{
                    result[index] = item;
                    resultIndex++;
                    if(resultIndex === arr.length){
                        resolve(result)
                    }  
                }
               
            })
        })
      
    }
    finally = (callback)=>{
        //无论什么样的状态都要执行回调函数,借助then方法在成功和失败的回调中都调用callback
        //finally返回一个promise对象,该对象的状态为调用finally的对象的状态,其实就是then方法的返回值。
        return this.then(value=>{
            // callback()
            // //传递给下一个then方法的参数为then方法相应状态的参数
            // return value
            //如果遇到异步任务,需要等到异步结果再把结果返回回去,可以借助上面写的resolve方法,讲callback得结果转为promise对象,在状态改变之后返回回去
           return MyPromise.resolve(callback()).then(()=>value)
        },reason=>{
            // callback()
            // //传递给下一个then方法的参数为then方法相应状态的参数,失败状态需要通过throw改变状态为reject。
            // throw reason
              //如果遇到异步任务,需要等到异步结果再把结果返回回去,可以借助上面写的resolve方法,讲callback得结果转为promise对象,在状态改变之后返回回去
             return MyPromise.resolve(callback()).then(()=>{throw reason})
        })
    }
    constructor(executor){
        try{
            executor(this.resolve,this.reject)
        }
        catch(err){
            this.reject(err)
        }
    }
    resolve = (value)=>{
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
            while(this.fulfilledCallback.length){
                this.fulfilledCallback.shift()()
            }
        }
    }
    reject = (reason)=>{
        if(this.status === PENDING){
            this.status = REJECTED;
            this.reason =reason;
            while(this.rejectedCallback.length){
                this.rejectedCallback.shift()()
            }
        }
    }
    then = (fulfilled,rejected)=>{
        fulfilled = fulfilled ? fulfilled :value=>value;
        rejected = rejected ? rejected :reason=>{throw reason};
        const promise2 = new MyPromise((resolve,reject)=>{
             if(this.status === FULFILLED){
                setTimeout(()=>{
                    try{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
            }
            else if(this.status === REJECTED){
                setTimeout(()=>{
                    try{
                        const x = rejected(this.reason)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
            }
            else{
                this.fulfilledCallback.push(()=>{
                      setTimeout(()=>{
                    try{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
                })
                this.rejectedCallback.push(()=>{
                     setTimeout(()=>{
                    try{
                        const x = rejected(this.reason)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
                });
            }
        })
       
        return promise2
    }
}
function resolvePromise(promise2,x,resolve,reject){
    if(promise2 === x){
       return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
    }
    if(x instanceof MyPromise){
        x.then(value=>resolve(value),reason=>reject(reason))
    }
    else{
        resolve(x)
    }
}
function p1(){
    return new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('p1')
        },2000)

    })
}
function p2(){
    return new MyPromise((resolve,reject)=>{
        resolve('p2')
    })
}
const promise1 = new MyPromise((resolve,rejct)=>{
    resolve(1)
}).finally(()=>{
    console.log("finally执行了")
   return p1()
}).then(value=>{
    console.log(value)
})

catch方法

catch方法接受一个失败的处理回调函数,用于失败状态的处理操作,并且可以继续使用then方法,所以他的返回值为promise对象

const PENDING = 'pening'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
    status = PENDING;
    value = undefined;
    reason = undefined;
    fulfilledCallback = [];
    rejectedCallback = [];
    static resolve(data){
        //判断data的类型,如果是promise类型的则原封不动的返回
        if(data instanceof MyPromise){
            return data
        }
        //如果是普通类型的则转换为promise对象返回
        else{
            return new MyPromise((resolve,reject)=>{
                resolve(data)
            })
        }
    }
    static all(arr){
        return new MyPromise((resolve,reject)=>{
            let result = [];
            let resultIndex = 0;
            arr.forEach((item,index)=>{
                if(item instanceof MyPromise){
                    item.then(value=>{
                        result[index] = value;
                        resultIndex++;
                        if(resultIndex === arr.length){
                            resolve(result)
                        }  
                    },reason=>reject(reason))
                }
                else{
                    result[index] = item;
                    resultIndex++;
                    if(resultIndex === arr.length){
                        resolve(result)
                    }  
                }
               
            })
        })
      
    }
    finally = (callback)=>{
        return this.then(value=>{
           return MyPromise.resolve(callback()).then(()=>value)
        },reason=>{
             return MyPromise.resolve(callback()).then(()=>{throw reason})
        })
    }
    catch = (fallBack)=>{
        //调catch方法会执行失败的操作,返回promise对象。
        return this.then(undefined,fallBack)
    }
    constructor(executor){
        try{
            executor(this.resolve,this.reject)
        }
        catch(err){
            this.reject(err)
        }
    }
    resolve = (value)=>{
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
            while(this.fulfilledCallback.length){
                this.fulfilledCallback.shift()()
            }
        }
    }
    reject = (reason)=>{
        if(this.status === PENDING){
            this.status = REJECTED;
            this.reason =reason;
            while(this.rejectedCallback.length){
                this.rejectedCallback.shift()()
            }
        }
    }
    then = (fulfilled,rejected)=>{
        fulfilled = fulfilled ? fulfilled :value=>value;
        rejected = rejected ? rejected :reason=>{throw reason};
        const promise2 = new MyPromise((resolve,reject)=>{
             if(this.status === FULFILLED){
                setTimeout(()=>{
                    try{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
            }
            else if(this.status === REJECTED){
                setTimeout(()=>{
                    try{
                        const x = rejected(this.reason)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
            }
            else{
                this.fulfilledCallback.push(()=>{
                      setTimeout(()=>{
                    try{
                        const x = fulfilled(this.value)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
                })
                this.rejectedCallback.push(()=>{
                     setTimeout(()=>{
                    try{
                        const x = rejected(this.reason)
                        resolvePromise(promise2,x,resolve,reject)
                    }
                    catch(err){
                        reject(err)
                    } 
                },0)
                });
            }
        })
       
        return promise2
    }
}
function resolvePromise(promise2,x,resolve,reject){
    if(promise2 === x){
       return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))
    }
    if(x instanceof MyPromise){
        x.then(value=>resolve(value),reason=>reject(reason))
    }
    else{
        resolve(x)
    }
}