《JavaScript ---- Promise》

138 阅读16分钟

Promise的使用

异步任务的处理

在学习promise之前,我们先来了解一下异步任务的处理,从一个实际的例子作为切入点:

  • 我们调用一个函数,这个函数中发送网络请求(我们可以用定时器来模拟)
  • 如果发送网络请求成功了,那么告知调用者发送成功,并且返回成功相关的数据
  • 如果发送网络请求失败了,那么告知调用者发送失败,并且返回失败报告

解决方案如下:

function requestData(url,successCallback,failureCallback){
    setTimeout(()=>{
        if(url === 'https://www.baidu.com'){
            successCallback("一组成功数据")
            // 发送成功执行
         }else{
             failureCallback("失败报告")
            //发送失败执行
    },1000)
    
   function successCallback(res){
       console.log(res)
   }    
   function failureCallback(err){
       console.log(err)
   }    

上面解决的方案中,我们可以解决请求函数得到结果后,获取对应的回调,但他存在两个主要的问题

  • 第一:我们需要自己设计回调函数、回调函数的名称、回调函数的使用
  • 第二:队医不同的人、不同的框架设计出来的方案是不同的,那么我们必须耐下心来看别人的源码或者文档,一边可以理解他这个函数怎么使用

ES6之后,ECMA推出了promise,提供统一的API接口,用来实现异步任务的处理

promise和promise的API

  • promise是一个类,可以翻译成承诺、许诺
  • 当我们需要给予到用着一个承诺:待会我给你回调数据时,就可以创建一个Pormise的对象
  • 通过new创建promise对象时,我们需要传入一个回调函数,我们成为executor
    • 这个回调函数会立即执行,并且回调函数有两个参数同样也是回调函数resolvereject
    • 当我们调用resolve回调函数的时候,就会执行Promise对象中的then方法传入的回调函数
    • 当我们调用reject回调函数的时候,就会执行Promise对象中的catch方法传入的回调函数

Promise的代码结构

const promise = new Promise((resolve,reject)=>{
    // 调用resolve,那么then传入的回调会被执行
    resolve("成功数据")
    // 调用reject,那么then传入的回调会被执行
    reject("错误信息")
}

//写法一
// then方法传入的回调函数两个回调函数:
// > 第一个回调函数, 会在Promise执行resolve函数时, 被回调
// > 第二个回调函数, 会在Promise执行reject函数时, 被回调
promise.then(res=>{
    console.log(res)
}).catch(err=>{
     console.log(err)
})

//写法二
//catch方法传入的回调函数, 会在Promise执行reject函数时, 被回调
promise.then(res=>{
    console.log(res)
},err=>{
    console.log(err)
})

上面Promise使用过程中,我们可以将它划分为三个状态:

  • 待定(pendding):初始状态,既没有对象,也没有拒绝,当执行executor中的代码时,处于该状态
  • 已兑现(fufilled):意味着操作成功完成,执行resolve时,处于该状态
  • 与拒绝(rejected):意味着操作失败,**执行reject时,处于该状态

有了Promise,我们就可以将之前的代码进行重构了:

function requestData(url){
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            if(url === "https://www.baidu.com"){
                resolve("一组成功的数据")
             }else{
                 reject("请求url错误")
             }
        },1000)
     }
 }    

Executor

Executor是在创建Promise时需要传入的一个回调函数,这个回调函数会被立即执行,并传入两个参数:

new Promise((resolve,reject)=>{
    console.log("111")
 })
//打印台会输出 111

通常我们会在Executor中确定我们的Promise状态

  • 通过resolve,可以兑现(fufiled)Promise的状态,我们也可以称之为已决议(resolved)
  • 通过reject,可以拒绝(reject)Promise的状态 注意:一旦状态确定下来,Promise的状态就会被锁死,该promise的状态是不可更改的
  • 在我们调用resolve的时候,如果resolve传入的值本身不是一个Promise,那么会将该Promise的状态变成兑(fulfilled)
  • 在之后我们去调用reject时,已经不会有任何的响应了(并不是这行代码不会执行,而是无法改变Promise状态);

resolve不同值的区别

  • 情况一:如果resolve传入的传入一个普通值或者对象,那么这个值会作为then回调的参数
  • 情况二:如果resolve传入的传入一个Promise对象,那么这个新的Promise会决定原Promise的状态
  • 情况三:如果resolve传入的对象,并且对象有实现then方法,那么会执行then方法,并且根据then方法的结果决定Promise的状态
//resolve传入普通参数  pending->fufilled
const newPromise = new Promise((resolve, reject) => {
    resolve("aaaaaa")
})

newPromise.then(res=>{
   console.log(res)     //aaaaaa
})

//resolve传入Promise对象
new Promise((resolve, reject) => {
   // pending -> fulfilled
    resolve(newPromise)
}).then(res => {
   console.log("res:", res)   //res: aaaaaa
})

//传入一个对象,这个对象有then方法
new Promise((resolve, reject) => {
   // pending -> fulfilled
   const obj = {
       then: function(resolve, reject) {
           // resolve("resolve message")
          reject("reject message")
        }
   }
   resolve(obj)
}).then(res => {
    console.log("res:", res)   // res : resolve message
}, err => {
    console.log("err:", err)  //err " reject message
})

then方法

then方法 - 接收两个参数

then方法时Promise对象上的一个方法:他其实是放在Promise的原型Peomise.prototype.then then方法接收两个参数: * fufilled的回调函数:当状态变为fufilled时会回调函数 * reject的回调函数:当状态变为reject时会回调函数

 promise.then(res=>{
      console.log(res)
  },err=>{
      console.log(err)
  })
  //等价于
   promise.then(res=>{
      console.log(res)
  }}.catch(err=>{
      console.log(err)
  })

then方法 - 多次调用

一个Promisethen方法是可以被对此调用的: * 每次调用我们都可以传入一个对应fufilled回调 * 当Promise的状态编程fufilled的时候,这些回调函数都会被执行

const promise = new Promise((resolve, reject) => {
     resolve("hahaha")
})
promise.then(res=>{
     console.log("res1":res)   // res1 :hahaha
})
promise.then(res=>{
     console.log("res2":res)  // res2 :hahaha
})
promise.then(res=>{
     console.log("res3":res)  // res3 :hahaha
})

then方法 -返回值

then方法本身是有返回值的,它的返回值是一个Promise,所以我们可以进行链式调用,但是then方法返回的Promise到底处于什么样的状态呢?

  • then方法中的回调函数本身在执行的时候,那么它处于pending状态
  • then方法中的回调函数返回一个结果时,那么它处于fulfilled状态,并且会将结果作为resolve的参数
    • 情况一:返回一个普通值
    • 情况二:返回一个Promise
    • 情况三:返回一个thenable对象
  • then方法抛出一个异常时,那么它处于reject状态

catch方法

catch方法时Promise对象上的一个方法:他其实是放在Promise的原型Peomise.prototype.catch

catch方法 - 多次调用

一个Promisecatch方法是可以被对此调用的: * 每次调用我们都可以传入一个对应rejecte回调 * 当Promise的状态编程reject的时候,这些回调函数都会被执行

const promise = new Promise((resolve, reject) => {
     reject("hahaha")
})
promise.catch(err=>{
     console.log("err1":err)   //err1 :hahaha
})
promise.catch(res=>{
     console.log("err2":err)  // err2 :hahaha
})
promise.catch(res=>{
     console.log("err3":err)  // err3 :hahaha
})

catch方法 - 返回值

catch方法本身是有返回值的,它的返回值是一个Promise,所以我们可以使用then方法或者catch方法进行链式调用

const promise = new Promise((resolve, reject) => {
      reject("hahaha")
 })
 promise.then(res => {
    console.log("res result:", res)
}).catch(err=>{
      //throw new Error('error message')    抛出错误会调用下一个catch的回调函数
      console.log("err1":err)   //err1 :hahaha
      return "catch return value"  //return 一个值 pendding-> fufilled   会调用下一个then的回调函数
 }).then(res => {
    console.log("res result:", res)  // res result:"catch return value"
 }).catch(err=>{
      console.log("err2":err)   // error message
 })     

finally方法

finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象无论变成fulfilled还是reject状态,最终都会被执行的代码。 finally方法是不接受参数的,因为无论是fulfilled还是reject状态他都执行

const promise = new Promise((resolve, reject) => {
  // resolve("resolve message")
  reject("reject message")
})

promise.then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err)  //err: reject message
}).finally(() => {
  console.log("finally code execute") // finally code execute
})

前面我们学习的thencatchfinally方法都属Promise的实例方法,都是存放在PromisePrototype上的 下面我们学习一下Promsise的方法

resolve方法

Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象

Promise.resolve()的用法相当于new Promise(),并且执行resolve操作:

Promise.resolve("aky")
//等价于
new Promise((resolve)=>resolve("aky"))

resolve参数的形态与对应的返回值

  • 情况一:参数是一个普通的值或者对象 ,返回这个值的promise对象
  • 情况二:参数本身是Promise,返回这个promise
  • 情况三:参数是一个thenable,返回的promise会“跟随”这个thenable的对象,采用它的最终状态

rejecte方法

reject方法类似于resolve方法,只是会将Promise对象的状态设置为reject状态。

Promise.re()的用法相当于new Promise(),并且执行reject操作:

Promise.reject("aky")
//等价于
new Promise((resolve,reject)=>reject("aky"))

Promise.reject传入的参数无论是什么形态,都会直接作为reject状态的参数传递到catch

all方法

Promise.all的作用是将多个Promise包裹在一起形成一个新的Promise

新的Promise状态由包裹的所有的Promise共同决定

  • 当所有的Promise状态编程fufilled状态时,新的Promise状态为fufilled,并且会将所有Promise的返回值组成一个数组
  • 当一个Promise状态为reject时,新的Promise状态为reject,并返回第一个reject的返回值作为参数
// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
 setTimeout(() => {
   resolve(11111)
 }, 1000);
})

const p2 = new Promise((resolve, reject) => {
 setTimeout(() => {
   resolve(22222)
   //reject(22222)
 }, 2000);
})

const p3 = new Promise((resolve, reject) => {
 setTimeout(() => {
   resolve(33333)
 }, 3000);
})

// 需求: 所有的Promise都变成fulfilled时, 再拿到结果
// 意外: 在拿到所有结果之前, 有一个promise变成了rejected, 那么整个promise是rejected
Promise.all([p1, p2, p3, "aaaa"]).then(res => {
 console.log(res)  //[11111,22222,33333,"aaaa"]
}).catch(err => {
 console.log("err:", err)   // err :2222
})

allSettled方法

Promise.all方法有一个缺陷:当其中一个Promise编程reject状态时,新的Promise就会立即编程对应的reject状态,那么对于resolve的,依然处于pendding状态的Promise,我们是获取不到结果的。

在ES11中,新添加了新的API Promise.allSettled

  • 该方法会在所有的Promise都有结果(settled),无论是fulfilled,还是rejected时,才会有最终的状态
  • 并且这个Promise的结果一定是fufilled
// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
 setTimeout(() => {
   resolve(11111)
 }, 1000);
})

const p2 = new Promise((resolve, reject) => {
 setTimeout(() => {
   reject(22222)
 }, 2000);
})

const p3 = new Promise((resolve, reject) => {
 setTimeout(() => {
   resolve(33333)
 }, 3000);
})

// allSettled
Promise.allSettled([p1, p2, p3]).then(res => {
 console.log(res)
}).catch(err => {
 console.log(err)
})
/**[
     { status: 'fulfilled', value: 11111 },
     { status: 'rejected', reason: 22222 },
     { status: 'fulfilled', value: 33333 }
]
*/

race方法

如果有一个Promise有了结果,我们就希望决定最终新Promise的状态,那么可以使用race方法

// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(11111)
  }, 3000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(22222)
  }, 500);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(33333)
  }, 1000);
})

// race: 竞技/竞赛
// 只要有一个Promise变成fulfilled状态, 那么就结束
// 意外: 
Promise.race([p1, p2, p3]).then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err)   //err :22222
})

any方法

any方法是ES12中新增的方法,和race方法是类似的

  • any方法会等到一个fulfilled状态,才会决定新Promise的状态
  • 如果所有的Promise都是reject的,那么也会等到所有的Promise都变成rejected状态
  • 如果所有的Promise都是rejected的,那么会报一个AggregateError的错误。

手写Promise的部分方法

Pormise类的实现

创建一个promise实例的时候会传入一个executor回调函数,并且执行这个函数,回调函数接收两个固定的函数参数resolvereject,作用是将pending状态变为fufilledrejected状态,并将成功数据或者错误报告保存起来

const PROMISE_STATUS_PENDING = "pending"
const PROMISE_STATUS_FUFILLED = "fufilled"
const PROMISE_STATUS_REJECT = "rejected"

class MyPromise {
    constructor(executor){
        this.status = PROMISE_STATUS_PENDING
        this.value =  undefined
        this.reason = undefined
  
        //定义resolve函数  把成功数据当作参数传入
        const resolve = (value)=>{
            //promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
            if(this.status === PROMISE_STATUS_PENDING){
                this.status = PROMISE_STATUS_FUFILLED //改变状态
                this.value = value  //保存成功数据
                
                console.log('resolve被调用') //测试用的
            }
        } 
         //定义reject函数,并把错位信息作为参数传入
         const reject = (reason) => {
              //promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
            if(this.status === PROMISE_STATUS_PENDING){
                this.status = PROMISE_STATUS_REJECT
                this.reason  = reason  // 保存错误信息
                
                console.log('reject被调用') //测试用的
             }   
          }
          
       executor(resolve,reject)  //执行erecutor回调函数
        
    }  
}    

创建promise的实例

const promise = new MyPromise((resolve,reject)=>{
    console.log("pending状态")
    resolve(1111)
    //reject(2222)
})

打印结果:

image.png

image.png

promise then方法的实现

promisethen方法也接收两个函数参数,onfufilledonrejected函数,分别在成功时调用并把数据传入,在失败是调用并把错误信息传入

const PROMISE_STATUS_PENDING = "pending"
const PROMISE_STATUS_FUFILLED = "fufilled"
const PROMISE_STATUS_REJECT = "rejected"

class MyPromise {
    constructor(executor){
        this.status = PROMISE_STATUS_PENDING
        this.value =  undefined
        this.reason = undefined
  
        //定义resolve函数  把成功数据当作参数传入
        const resolve = (value)=>{
            //promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
            if(this.status === PROMISE_STATUS_PENDING){
                this.status = PROMISE_STATUS_FUFILLED //改变状态
                queueMicrotask(() => {
                    this.value = value
                    this.onFulfilled(this.value)
                });
            }
        } 
         //定义reject函数,并把错位信息作为参数传入
         const reject = (reason) => {
              //promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
            if(this.status === PROMISE_STATUS_PENDING){
                this.status = PROMISE_STATUS_REJECT
                queueMicrotask(() => {
                    this.reason = reason
                    this.onRejected(this.reason)
                })
             }   
          }
          
       executor(resolve,reject)  //执行erecutor回调函数
        
    }  
    
    // then方法的实现
    then(onFufilled,onRejected){
        this.onFufilled = onFufilled
        this.onFejected = onRejected
        
}    

使用queueMicrotask方法包裹的原因:在创建新的promise实例的时候会自行executor回到函数,那么就会去执行resolve或者reject函数,如果没有用queueMicrotask方法包裹,代码顺序执行,此时then方法没有调用执行,此时onFufilledonRejected还没有传值,所以会报错onFufilled is not function,onRejected is not function;queueMicrotask属于微任务,在下一次事件循环中执行,在主线程执行完成后在执行

then方法实现的优化

优化一: then方法多次执行和确定Promise状态后,再次调用then

上面实现的then方法不能还进行多次调用

const promise = new MyPromise((resolve,reject)=>{
    console.log("pending状态")
    resolve(1111)
    //reject(2222)
})
// 调用then方法多次调用
promise.then(res => {
  console.log("res1:", res)
}, err => {
  console.log("err:", err)
})

promise.then(res => {
  console.log("res2:", res)
}, err => {
  console.log("err2:", err)
}) 

//执行结果为 res2: 1111 

多次调用then方法,由于我们对onFufilledonRejected使用的时赋值操作,所以后面的回调函数会覆盖前面的,我们希望的时多次调用能够多次执行。

我们可以将onFufilledonRejected回调函数保存到一个数组中,执行resolvereject的时候遍历执行

class MyPromise {
    constructor(executor){
        this.status = PROMISE_STATUS_PENDING
        this.value =  undefined
        this.reason = undefined
        
        this.onFufilledFns = []    //存储多次调用then成功的回调
        this.onRejectedFns = []    //存储多次调用then失败的回调
        //定义resolve函数  把成功数据当作参数传入
        const resolve = (value)=>{
            //promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
            if(this.status === PROMISE_STATUS_PENDING){ 
                queueMicrotask(() => {
                    if(this.status! == PROMISE_STATUS_PENDING) return
                    this.status = PROMISE_STATUS_FUFILLED //改变状态
                    this.value = value
                    //this.onFulfilled(this.value)
                    //遍历成功的回调
                    this.onFufilledFns.forEavch((onFufilled)=>{
                        onFufilled(this.value)
                    })
                })
            }
        } 
         //定义reject函数,并把错位信息作为参数传入
         const reject = (reason) => {
              //promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
            if(this.status === PROMISE_STATUS_PENDING){
                //添加微任务
                queueMicrotask(() => {
                    if(this.status! == PROMISE_STATUS_PENDING) return
                    this.status = PROMISE_STATUS_REJECT
                    this.reason = reason
                    //this.onRejected(this.reason)
                    //遍历失败的回调
                    this.onFufilledFns.forEavch((onRejected)=>{
                        onRejected(this.value)
                    })
                })
                })
             }   
          }
          
       executor(resolve,reject)  //执行erecutor回调函数
        
    }  
    
    // then方法的实现
    then(onFufilled,onRejected){
        // 1、如果then调用的时候,状态已经确定下来了
        if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
              onFulfilled(this.value)
        }
        if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
              onRejected(this.reason)
        }
        
        // 2.将成功回调和失败的回调放到数组中
        if (this.status === PROMISE_STATUS_PENDING) {
            //this.onFufilled = onFufilled
             this.onFulfilledFns.push(onFulfilled) //将成功回调放到数组中
           //this.onFejected = onRejected
            this.onRejectedFns.push(onRejected)  //将失败的回调放到数组中 
         }   
    }
}    
const promise = new HYPromise((resolve, reject) => {
  console.log("状态pending")
  resolve(1111) // resolved/fulfilled
  reject(2222)
})

// 调用then方法多次调用
promise.then(res => {
  console.log("res1:", res)
}, err => {
  console.log("err:", err)
})

promise.then(res => {
  console.log("res2:", res)
}, err => {
  console.log("err2:", err)
})
//在确定Promise状态之后, 再次调用then
setTimeout(() => {
  promise.then(res => {
    console.log("res3:", res)
  }, err => {
    console.log("err3:", err)
  })
}, 1000)

image.png

优化二: then方法的链式调用

then方法能链式调用的原因:then方法返回值仍然是Promise对象,上面代码中的then需要返回一个promise

// 工具函数
function execFunctionWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    resolve(result)
  } catch(err) {
    reject(err)
  }
}
class MyPromise {
    .... // 上面代码
     
     then(onFufilled,onRejected){
         return new MyPromise((resolve,reject)=>{
                // 1、如果then调用的时候,状态已经确定下来了
                if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                      //const newValue =onFulfilled(this.value) //拿到执行成功回调的返回值
                      //resolve(newValue)
                      //try {
                      //      const newValue = onFulfilled(this.value)
                      //      resolve(newValue)
                      // } catch(err) {
                      //      reject(err)
                      //}
                      
                      execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
                }
                if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                     //cosnt newReason =  onRejected(this.reason) //拿到执行失败回调的返回值
                     //resolve(newReason)
                     // try {
                     //       cosnt newReason =  onRejected(this.reason)
                     //       resolve(newReason)
                     // } catch(err) {
                     //       reject(err)
                     // }
                      execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
                }
        
                // 2.将成功回调和失败的回调放到数组中
                if (this.status === PROMISE_STATUS_PENDING) {
                    //this.onFufilled = onFufilled
                     this.onFulfilledFns.push(()=>{
                         //const newValue = onFulfilled(this.value)
                         //resolve(newValue)
                         //try {
                         //   const newValue = onFulfilled(this.value)
                         //   resolve(newValue)
                         // } catch(err) {
                         //       reject(err)
                         // }
                          execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
                     }) //将成功回调放到数组中
                   //this.onFejected = onRejected
                    this.onRejectedFns.push(()=>{
                        //const newReason = onRejected(this.reason)
                        //resolve(newReason)
                        //try {
                        //    cosnt newReason =  onRejected(this.reason)
                        //    resolve(newReason)
                        // } catch(err) {
                        //    reject(err)
                        // }
                          execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
                    })  //将失败的回调放到数组中 
                 }   
 
         })
}       
const promise = new MyPromise((resolve, reject) => {
  console.log("状态pending")
  // resolve(1111) // resolved/fulfilled
  reject(2222)
  // throw new Error("executor error message")
})

// 调用then方法多次调用
promise.then(res => {
  console.log("res1:", res)
  return "aaaa"
  // throw new Error("err message")
}, err => {
  console.log("err1:", err)
  return "bbbbb"
  // throw new Error("err message")
}).then(res => {
  console.log("res2:", res)
}, err => {
  console.log("err2:", err)
})

//结果:状态pending   err1:2222  res2:bbbb

catch方法实现

catch方法会在promise状态为rejected时候调用并传入错误信息,其实本质上为then方法分别传入undefinedonRejected参数


class MyPromise {
    ....//  省略
    
    then(onFufilled,onRejected){
      //将上一次为执行的失败的回调抛出
       const defalutOnRejected = err =>{throw err}
       onRejected = onRejected || defalutOnRejected
       return new MyPromise((resolve,reject)=>{
        // 1、then调用的时候promise状态已经为fufilled
        if(this.status === PROMISE_STATUS_FUFILLED && onfufilled){
            try{
                cosnt newValue = onfufilled(this.value)
                resolve(newValue)    
             }catch(err){
                 reject(err)
             }
        }
        if(this.status === PROMISE_STATUS_REJECT && onREJECTED){
            try{
                cosnt newReason = onRejected(this.value)
                resolve(newReason)    
             }catch(err){
                 reject(err)
             }
        }
       // 2 、 将成功的回调放入回回调数组中
       if(this.status === PROMISE_STATUS_PENDING){
          if(onFufilled) this.onfufilled.push(()=>{
              try{
                cosnt newValue = onFufilled(this.value)
                resolve(newValue)    
             }catch(err){
                 reject(err)
             
          })
          if(onRejected) this.onrejected.push(()=>{
              try{
                cosnt newReason = onRejected(this.value)
                resolve(newReason)    
             }catch(err){
                 reject(err)
             }
          })
       }
    }) 
 }
 
 
 
 catch(undefined,onReject){
     this.then(undefined,onReject)
 }

finally方法实现

finally方法本质就是调用then方法,并且传入回到函数

calss MyPromise {
    ....
    
    finally (onFinally){
        this.then(()=>{
            onFinally()
        },()=>{
            onFinally()
        })

all和allSettled方法实现

all方法的实现关键是什么时候执行resolve,什么时候执行reject


class  MyPromise {
    
    
    
    static all(promisesArr){
        return new MyPromise((resolve,reject)=>{
            const values = []
            promisesArr.forEach(promise=>{
                promise.then(res=>{
                    value.push(res)
                    if(values.length ===promisesArr.length){
                        resolve(values)
                },err=>{
                    reject(err)
                })
            })
        })
    }
    
    
    static allSettled(promisesArr)[
        return new MyPromise((resolve,reject)=>{
            const results = []
            promise.forEach((promise)=>{
                promise.then(res=>{
                    results.push({status:PROMISE_STATUS_FUFILLED,value:res})
                    if(results.length ===promise.length){
                        resolve(results)
                    }    
                },err=>{
                    results.push({status:PROMISE_STATUS_REJECT,value:err})
                    if (results.length === promises.length) {
                        resolve(results)
                      }
                })
            })           
        })           
}

race方法实现

class Mypromise {
    
    ...
    
    
    static race(promises) {
    return new HYPromise((resolve, reject) => {
      promises.forEach(promise => {
        // promise.then(res => {
        //   resolve(res)
        // }, err => {
        //   reject(err)
        // })
        promise.then(resolve, reject)
      })
    })
  } 

总结

MyPromise各个方法实现的总代码如下

//工具函数
function execFunctionWithCatchError(execFn,value,resolve,reject){
    try{
        const result = execFn(value)
        resolve(reslut)
    }catch(err){
        reject(err)
    }    
}

class Mypromise{
    const PROMISE_STATUS_PENDING = 'pending'
    const PROMISE_STATUS_FULFILLED = 'fulfilled'
    const PROMISE_STATUS_REJECTED = 'rejected'
    constructor(executor){
        this.status = PROMISE_STATUS_PENDING 
        this.value = undefined
        this.reson = undefined
        this.onFufilledFns = []
        this.onRejectedFns = []
        //resolve函数
        const resolve = (value)=> {
            if(this.status === PROMISE_STATUS_PENDING ){
            //微任务
             queueMicrotask(() => {
                 this.status = PROMISE_STATUS_FULFILLED
                 this.value = value
                 this.onFufilledFns.forEach((fn)=>{
                     fn(this.value)
                 })
             }
        }
        //reject函数
        const reject = (reason) => {
            if(this.status === PROMISE_STATUS_PENDING){
                //微任务
                queueMicrotask(()=>{
                    this.status = PROMISE_STATUS_REJECTED 
                    this.reason = reason
                    this.onRejectedFns.forEach(fn=>{
                        fn(this.reason)
                    })  
                })
        }
        executor(resolve,reject)
    }
    
    
    //then方法
    
    then(onFufilled,onRejected){
        const defaultOnRejected = (err) =>{ throw err}
        onRejected = onRejected || defaultOnRejected
        return new MyPromise((resolve,reject)=>{
            // then方法执行的时候,promise状态已经是fufilled
            if(this.status === PROMISE_STATUS_FULFILLED && onFufilled){
                execFunctionWithCatchError(onFufilled,this,value,resolve,reject)
            }
            if(this.status ===PROMISE_STATUS_REJECTED && onRejected){
                execFunctionWithCatchError(onFufilled,this,value,resolve,reject)
            }
            
            //then方法仍是pending状态下,将成功或者失败回调添加数组中
            if(this.status === PROMISE_STATUS_PENDING){
                if(onFufilled) this.onFufilledFns.push(()=>{
                    execFunctionWithCatchError(onFufilled,this,value,resolve,reject)
                })
            
                 if (onRejected) this.onRejectedFns.push(() => {
                    execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
                })   
            }
       })
    }
    
    
    //catch方法
    catch(onRejected){
        return this.then(undefined,onRejected)
    }
    //finally方法
    finally(onfinally){
        this.then(res=>{
            onfinally()
        },err=>{
            onfinally()
        })
    }
    
    //all方法
    static all(promsiesArr){
        const values = []
        return new MyPrmoise((resolve,reject)=>{
            promsiesArr.forEach(promise=>{
                promsie.then(res=>{
                    values.push(res)
                    if(values.length === promisesArr.length){
                        resolve(values)
                    }
                },err=>{
                    reject(err)
                })
            })
        })
    
    //allSettled方法
    static allSettled(promsiesArr){
        return new MyPromise((resolve,reject)=>{
            const results = []
            promisesArr.forEach(promise=>{
                promsie.then(res=>{
                    resluts.push({status:PROMISE_STATUS_FULFILLED,value:res})
                    if(result.length === promisesArr.length){
                        resolve(values)
                    }
                },err=>{
                    results.push({status:PROMISE_STATUS_REJECTED,value:err})
                    if(results.length === promisesArr.length){
                        resolve(values)
                    }
                })
            })
        })
    }
    
    //race方法
    static race(promises) {
         return new HYPromise((resolve, reject) => {
              promises.forEach(promise => {
                    // promise.then(res => {
                    //   resolve(res)
                    // }, err => {
                    //   reject(err)
                    // })
                    promise.then(resolve, reject)
              })
        })
    }
}