JS 手写Promise

作者: 咸鱼不咸_123 | 来源:发表于2022-05-15 23:55 被阅读0次

    二、手写Promise

    1.Promise的设计和构造方法

    const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_REJECTED="rejected";
    // * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
    class HYPromise{
      // * 记录状态
      constructor(executor) {
        // * 保存Promise的状态
        this.status=PROMISE_STATUS_PENDING;
        // * 保存传入的值
        this.value=undefined;
        this.reason=undefined;
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            this.status=PROMISE_STATUS_FULFILLED;
            this.value=value;
            console.log("resolve被调用");
          }
         
        }
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            this.status=PROMISE_STATUS_REJECTED;
            this.reason=reason;
            console.log("reject被调用");
          }
         
        }
        executor(resolve,reject)
      }
    }
    
    const promise=new HYPromise((resolve,reject)=>{
      console.log("状态pending");
      resolve("1111")
    })
    
    

    2.then方法的设计

     const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_REJECTED="rejected";
    // * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
    class HYPromise{
      // * 记录状态
      constructor(executor) {
        // * 保存Promise的状态
        this.status=PROMISE_STATUS_PENDING;
        // * 保存传入的值
        this.value=undefined;
        this.reason=undefined;
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            this.status=PROMISE_STATUS_FULFILLED;
            queueMicrotask(()=>{ //* 定时器是一个宏任务,会放在下一次事件循环时使用
            
              this.value=value;
              console.log("resolve被调用");
              // * 执行then传入进来的第一个回调函数
              this.onFulfilled(this.value)
            
          })
          }
         
         
        }
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            this.status=PROMISE_STATUS_REJECTED;
           queueMicrotask(()=>{
            this.reason=reason;
            console.log("reject被调用");
            // * 执行then传入进来的第二个回调函数
            this.onRejected(this.reason);
           })
          }
         
        }
        executor(resolve,reject)
      }
      then(onFulfilled,onRejected){
        this.onFulfilled=onFulfilled;
        this.onRejected=onRejected;
      }
     
    }
    
    const promise=new HYPromise((resolve,reject)=>{
      console.log("状态pending");
      // resolve("1111")
      reject("reject message")
    })
    
    promise.then(res=>{
      console.log("res:",res);
    },err=>{
      console.log("err:",err);
    })
    
    promise.then(res=>{
      console.log("res2:",res);
    },err=>{
      console.log("err2:",err);
    })
    
    // * 多次调用then,后面的then方法会覆盖前面的then方法,而且只会调用一次方法
    // * then方法不能实现链式调用
    

    3.then方法的优化一

    • 实现then多次调用
    • 如果Promise状态已经确定,再次调用then方法,传入的回调函数应该直接执行
     const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_REJECTED="rejected";
    // * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
    class HYPromise{
      // * 记录状态
      constructor(executor) {
        // * 保存Promise的状态
        this.status=PROMISE_STATUS_PENDING;
        // * 保存传入的值
        this.value=undefined;
        this.reason=undefined;
        this.onFulfilledFns=[];
        this.onRejectedFns=[];
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            queueMicrotask(()=>{ //* 定时器是一个宏任务,会放在下一次事件循环时使用
              this.status=PROMISE_STATUS_FULFILLED;
              this.value=value;
              console.log("resolve被调用");
              // * 执行then传入进来的第一个回调函数
             this.onFulfilledFns.forEach(Fn=>{
               Fn(this.value)
             })
            
          })
          }
         
         
        }
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
           
           queueMicrotask(()=>{ 
             this.status=PROMISE_STATUS_REJECTED;
            this.reason=reason;
            console.log("reject被调用");
            // * 执行then传入进来的第二个回调函数
            this.onRejectedFns.forEach(Fn=>{
              Fn(this.reason)
            })
           })
          }
         
        }
        executor(resolve,reject)
      }
      then(onFulfilled,onRejected){
        // 1.如果then方法调用的时候,状态已经确定下来了,应该直接执行的
        if(this.status===PROMISE_STATUS_FULFILLED&&onFulfilled){
          onFulfilled(this.value);
        }else if(this.status===PROMISE_STATUS_REJECTED&&onRejected){
          onRejected(this.reason)
        }else{
          // 将成功回调和失败回调添加到数组中
        this.onFulfilledFns.push(onFulfilled);
        this.onRejectedFns.push(onRejected);
        }
        
      }
     
    }
    
    const promise=new HYPromise((resolve,reject)=>{
      console.log("状态pending");
      resolve("1111");//resolved/fulfilled
    })
    
    promise.then(res=>{
      console.log("res:",res);
    },err=>{
      console.log("err:",err);
    })
    
    promise.then(res=>{
      console.log("res2:",res);
    },err=>{
      console.log("err2:",err);
    })
    
    
    
    setTimeout(()=>{
      promise.then(res=>{
        console.log(res);
      })
    },1000)
    
    // * 解决了then方法的多次调用
    // * 在确定Promise状态之后,再次调用then
    // const promise2=new Promise((resolve,reject)=>{
    //   resolve("aaaaa");
    // })
    
    // setTimeout(()=>{
    //   promise2.then(res=>{ //原生编写了
    //     console.log(res);
    //   })
    // },1000)
    

    4.then方法的优化二

    • 实现了一个链式调用(返回一个新的Promise对象,使用新的Promise对象的resolve方法去处理对应的回调函数的返回值)
    • 实现了对executor执行时发生异常(错误),应该执行reject函数
    • 后面封装了一个工具函数,用来处理异常和回调
     const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_REJECTED="rejected";
    
    // 工具函数
    function execFunctionWithCatchError(exeFn,value,resolve,reject){
      try{
        let result=exeFn(value);
        reject(result);
      }catch(err){
        reject(err);
      }
    }
    // * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
    class HYPromise{
      // * 记录状态
      constructor(executor) {
        // * 保存Promise的状态
        this.status=PROMISE_STATUS_PENDING;
        // * 保存传入的值
        this.value=undefined;
        this.reason=undefined;
        this.onFulfilledFns=[];
        this.onRejectedFns=[];
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            // * 添加微任务
            queueMicrotask(()=>{ //* 定时器是一个宏任务,会放在下一次事件循环时使用
              if(this.status!==PROMISE_STATUS_PENDING) return;
              this.status=PROMISE_STATUS_FULFILLED;
              this.value=value;
              // console.log("resolve被调用");
              // * 执行then传入进来的第一个回调函数
             this.onFulfilledFns.forEach(Fn=>{
               Fn(this.value);
             })
            
          })
          }
         
         
        }
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
          //  * 添加微任务
           queueMicrotask(()=>{ 
             if(this.status!==PROMISE_STATUS_PENDING) return;
             this.status=PROMISE_STATUS_REJECTED;
            this.reason=reason;
            // console.log("reject被调用");
            // * 执行then传入进来的第二个回调函数
            this.onRejectedFns.forEach(Fn=>{
              Fn(this.reason)
            })
           })
          }
         
        }
    
        // * 在调用executor时判断里面是否抛出异常
        try{
          executor(resolve,reject)
        }catch(err){
          reject(err)
        }
      }
      then(onFulfilled,onRejected){
       
        return new HYPromise((resolve,reject)=>{
           // 1.如果then方法调用的时候,状态已经确定下来了,应该直接执行的
        if(this.status===PROMISE_STATUS_FULFILLED&&onFulfilled){
          execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
        }else if(this.status===PROMISE_STATUS_REJECTED&&onRejected){
          execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
        }else{
          // 将成功回调和失败回调添加到数组中
        this.onFulfilledFns.push(()=>{
          execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
        });
        this.onRejectedFns.push(()=>{
          execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
     });
        }
        })
      }
     
    }
    
    const promise=new HYPromise((resolve,reject)=>{
      // console.log("状态pending");
      // resolve("1111");//resolved/fulfilled
      reject("2222")
      // throw new Error("创建就报的异常")
    })
    
    promise.then(res=>{
      console.log("res:",res);
      return "aaaa"
    
    },err=>{
      console.log("err:",err);
      return "err bbb"
    }).then(res=>{
      console.log("res2:",res);
    },err=>{
      console.log("err2:",err);
    })
    
    // * 1. 实现了链式调用,链式调用的前提是返回一个新的HYPromise,最重要的是 什么时候执行resolve,什么时候执行reject
    // * 一般在正常情况下,无论原HYPromise的状态是如何,后面都会执行新的HYPromise的resolve,并将其值作为参数
    // * 只有在代码发生异常时(错误),才会让新的HYPromise执行reject
    
    // * 2. 在HYPromise的executor执行过程中如果发生异常,应该要执行reject
    
    
    

    5.catch方法的设计

    • catch只会接受一个onRejected的回调函数
      • 在内部调用then方法,设置then方法的第一个参数为undefined,第二个参数的值为onRejected
      // * catch方法的设计
      catch(onRejected){
        this.then(undefined,onRejected);
      }
    

    但是这样还是不能捕获原Promise对象的rejected状态,因为这个catch方法是针对新的Promise的rejected的状态,如果想要捕获原Promise的rejected状态,需要抛出异常,新的Promise对象的catch方法才能捕获到。

    所以我们需要改写then方法:

    • 在方法内部前面判断第二个参数是否有值,如果没有值,就重新赋值为一个函数,函数内部抛出一个异常

    这样在新的Promise就能捕获到原来的promise的rejected的状态

     then(onFulfilled,onRejected){
       onRejected=onRejected||(err=>{throw err})
        //以下代码省略...
      }
    

    全部的代码如下:

     const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_REJECTED="rejected";
    
    // 工具函数
    function execFunctionWithCatchError(exeFn,value,resolve,reject){
      try{
        let result=exeFn(value);
        reject(result);
      }catch(err){
        reject(err);
      }
    }
    // * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
    class HYPromise{
      // * 记录状态
      constructor(executor) {
        // * 保存Promise的状态
        this.status=PROMISE_STATUS_PENDING;
        // * 保存传入的值
        this.value=undefined;
        this.reason=undefined;
        this.onFulfilledFns=[];
        this.onRejectedFns=[];
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            // * 添加微任务
            queueMicrotask(()=>{ //* 定时器是一个宏任务,会放在下一次事件循环时使用
              if(this.status!==PROMISE_STATUS_PENDING) return;
              this.status=PROMISE_STATUS_FULFILLED;
              this.value=value;
              // console.log("resolve被调用");
              // * 执行then传入进来的第一个回调函数
             this.onFulfilledFns.forEach(Fn=>{
               Fn(this.value);
             })
            
          })
          }
         
         
        }
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
          //  * 添加微任务
           queueMicrotask(()=>{ 
             if(this.status!==PROMISE_STATUS_PENDING) return;
             this.status=PROMISE_STATUS_REJECTED;
            this.reason=reason;
            // console.log("reject被调用");
            // * 执行then传入进来的第二个回调函数
            this.onRejectedFns.forEach(Fn=>{
              Fn(this.reason)
            })
           })
          }
         
        }
    
        // * 在调用executor时判断里面是否抛出异常
        try{
          executor(resolve,reject)
        }catch(err){
          reject(err)
        }
      }
      then(onFulfilled,onRejected){
       onRejected=onRejected||(err=>{throw err})
        return new HYPromise((resolve,reject)=>{
           // 1.如果then方法调用的时候,状态已经确定下来了,应该直接执行的
        if(this.status===PROMISE_STATUS_FULFILLED&&onFulfilled){
          execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
        }else if(this.status===PROMISE_STATUS_REJECTED&&onRejected){
          execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
        }else{
          // 将成功回调和失败回调添加到数组中
        if(onFulfilled)this.onFulfilledFns.push(()=>{
          execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
        });
        if(onRejected)this.onRejectedFns.push(()=>{
          execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
     });
        }
        })
      }
     
      // * catch方法的设计
      catch(onRejected){
        this.then(undefined,onRejected);
      }
    }
    
    const promise=new HYPromise((resolve,reject)=>{
      console.log("状态pending");
      // resolve("1111");//resolved/fulfilled
      reject("2222")
      // throw new Error("创建就报的异常")
    })
    
    
    promise.then(res=>{
      console.log("res:",res);
    },err=>{
      console.log("err1:",err);
    }).catch(err=>{ 
      console.log("err:",err);
    })
    

    6.finally方法的设计

    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_REJECTED="rejected";
    
    // 工具函数
    
    function execFunctionWithCatchError(exeFn,value,resolve,reject){
      try{
        const result=exeFn(value);
        resolve(result);
      }catch(err){
        reject(err);
      }
    }
    class HYPromise{
      constructor(executor){
        this.status=PROMISE_STATUS_PENDING;
        this.value=undefined;
        this.reason=undefined;
        // this.onFulfilled=undefined;
        // this.onRejected=undefined;
        this.onFulfilledFns=[];
        this.onRejectedFns=[];
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            // * 原生执行then方法时是一个微任务
            queueMicrotask(()=>{
              if(this.status!==PROMISE_STATUS_PENDING) return; 
              this.status=PROMISE_STATUS_FULFILLED;
              this.value=value;
              //  * 执行then传入进来的回调函数
              // this.onFulfilled(this.value);
              this.onFulfilledFns.forEach(Fn=>{
                Fn(this.value);
              })
            })
          }
         
        }
    
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
           queueMicrotask(()=>{
             if(this.status!==PROMISE_STATUS_PENDING) return; 
            this.status=PROMISE_STATUS_REJECTED;
            this.reason=reason;
            // * 执行then传入进来的第二个参数
            // this.onRejected(this.reason);
            this.onRejectedFns.forEach(Fn=>{
              Fn(this.reason);
            })
           })
    
         }
        }
        try{
        executor(resolve,reject)
        }catch(err){
          reject(err);
        }
        
      }
    
      then(onFulfilled,onRejected){
         onRejected=onRejected|| (err=>{ throw err});
         onFulfilled=onFulfilled|| (value=>value)
        return new HYPromise((resolve,reject)=>{
          if(this.status==PROMISE_STATUS_FULFILLED&&onFulfilled){
            execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
          }else if(this.status==PROMISE_STATUS_REJECTED&&onRejected){
            execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
          }else{
            if(onFulfilled)this.onFulfilledFns.push(()=>{
            execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
            });
            if(onRejected)this.onRejectedFns.push(()=>{
            execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
            });
          }
        })
       
      }
      catch(onRejected){
        return this.then(undefined,onRejected);
      }
    
      finally(onFinally){
        return this.then(()=>{
          onFinally();
        },()=>{
          onFinally();
        })
      }
    }
    
    const promise=new HYPromise((resolve,reject)=>{
      console.log("状态pending");
      // reject("111");
      resolve("222");
      // throw new Error("pending err")
      
    })
    
    
    promise.then(res=>{
      console.log("res:",res);
    }).catch(err=>{
      console.log("catch err:",err);
    }).finally(()=>{
      console.log("finally方法实现");
    })
    // * 实现finally方法
    
    
    

    7.类方法 resolve和reject的设计

    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_REJECTED="rejected";
    
    // 工具函数
    
    function execFunctionWithCatchError(exeFn,value,resolve,reject){
      try{
        const result=exeFn(value);
        resolve(result);
      }catch(err){
        reject(err);
      }
    }
    class HYPromise{
      constructor(executor){
        this.status=PROMISE_STATUS_PENDING;
        this.value=undefined;
        this.reason=undefined;
        // this.onFulfilled=undefined;
        // this.onRejected=undefined;
        this.onFulfilledFns=[];
        this.onRejectedFns=[];
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            // * 原生执行then方法时是一个微任务
            queueMicrotask(()=>{
              if(this.status!==PROMISE_STATUS_PENDING) return; 
              this.status=PROMISE_STATUS_FULFILLED;
              this.value=value;
              //  * 执行then传入进来的回调函数
              // this.onFulfilled(this.value);
              this.onFulfilledFns.forEach(Fn=>{
                Fn(this.value);
              })
            })
          }
         
        }
    
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
           queueMicrotask(()=>{
             if(this.status!==PROMISE_STATUS_PENDING) return; 
            this.status=PROMISE_STATUS_REJECTED;
            this.reason=reason;
            // * 执行then传入进来的第二个参数
            // this.onRejected(this.reason);
            this.onRejectedFns.forEach(Fn=>{
              Fn(this.reason);
            })
           })
    
         }
        }
        try{
        executor(resolve,reject)
        }catch(err){
          reject(err);
        }
        
      }
    
      then(onFulfilled,onRejected){
         onRejected=onRejected|| (err=>{ throw err});
         onFulfilled=onFulfilled|| (value=>value)
        return new HYPromise((resolve,reject)=>{
          if(this.status==PROMISE_STATUS_FULFILLED&&onFulfilled){
            execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
          }else if(this.status==PROMISE_STATUS_REJECTED&&onRejected){
            execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
          }else{
            if(onFulfilled)this.onFulfilledFns.push(()=>{
            execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
            });
            if(onRejected)this.onRejectedFns.push(()=>{
            execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
            });
          }
        })
       
      }
      catch(onRejected){
        return this.then(undefined,onRejected);
      }
    
      finally(onFinally){
        return this.then(()=>{
          onFinally();
        },()=>{
          onFinally();
        })
      }
      static resolve(value){
        return new HYPromise((resolve,reject)=>{
          resolve(value);
        })
      }
      static reject(reason){
        return new HYPromise((resolve,reject)=>{
          reject(reason);
        })
      }
    }
    
    HYPromise.resolve(123).then(res=>{
      console.log("res:",res);
    })
    
    HYPromise.reject("err message").catch(err=>{
      console.log("err:",err);
    })
    
    
    // * 实现了类方法 resolve和reject方法
    
     
    

    8. 类方法 all 和allSettled

    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_REJECTED="rejected";
    
    // 工具函数
    
    function execFunctionWithCatchError(exeFn,value,resolve,reject){
      try{
        const result=exeFn(value);
        resolve(result);
      }catch(err){
        reject(err);
      }
    }
    class HYPromise{
      constructor(executor){
        this.status=PROMISE_STATUS_PENDING;
        this.value=undefined;
        this.reason=undefined;
        // this.onFulfilled=undefined;
        // this.onRejected=undefined;
        this.onFulfilledFns=[];
        this.onRejectedFns=[];
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            // * 原生执行then方法时是一个微任务
            queueMicrotask(()=>{
              if(this.status!==PROMISE_STATUS_PENDING) return; 
              this.status=PROMISE_STATUS_FULFILLED;
              this.value=value;
              //  * 执行then传入进来的回调函数
              // this.onFulfilled(this.value);
              this.onFulfilledFns.forEach(Fn=>{
                Fn(this.value);
              })
            })
          }
         
        }
    
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
           queueMicrotask(()=>{
             if(this.status!==PROMISE_STATUS_PENDING) return; 
            this.status=PROMISE_STATUS_REJECTED;
            this.reason=reason;
            // * 执行then传入进来的第二个参数
            // this.onRejected(this.reason);
            this.onRejectedFns.forEach(Fn=>{
              Fn(this.reason);
            })
           })
    
         }
        }
        try{
        executor(resolve,reject)
        }catch(err){
          reject(err);
        }
        
      }
    
      then(onFulfilled,onRejected){
         onRejected=onRejected|| (err=>{ throw err});
         onFulfilled=onFulfilled|| (value=>value)
        return new HYPromise((resolve,reject)=>{
          if(this.status==PROMISE_STATUS_FULFILLED&&onFulfilled){
            execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
          }else if(this.status==PROMISE_STATUS_REJECTED&&onRejected){
            execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
          }else{
            if(onFulfilled)this.onFulfilledFns.push(()=>{
            execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
            });
            if(onRejected)this.onRejectedFns.push(()=>{
            execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
            });
          }
        })
       
      }
      catch(onRejected){
        return this.then(undefined,onRejected);
      }
    
      finally(onFinally){
        return this.then(()=>{
          onFinally();
        },()=>{
          onFinally();
        })
      }
      static resolve(value){
        return new HYPromise((resolve,reject)=>{
          resolve(value);
        })
      }
      static reject(reason){
        return new HYPromise((resolve,reject)=>{
          reject(reason);
        })
      }
      static all(promises){
        // * 问题关键:什么时候执行resolve,什么时候执行reject
       return new HYPromise((resolve,reject)=>{
         let values=[];
          promises.forEach(promise=>{
            promise.then(res=>{
               values.push(res);
               if(values.length==promises.length) resolve(values);
            }).catch(err=>{
               reject(err);
            })
          })
       })
      }
      static allSettled(promises){
        
        return new Promise((resolve)=>{
          let results=[];
          promises.forEach(promise=>{
            promise.then(res=>{
              results.push({status:PROMISE_STATUS_FULFILLED,value:res})
              if(results.length==promises.length)
              resolve(results);
            }).catch(err=>{
              results.push({status:PROMISE_STATUS_REJECTED,value:err})
              if(results.length==promises.length)
              resolve(results);
            })
          })
        })
      }
    }
    
    const p1=new Promise((resolve)=>{
      setTimeout(()=>{
        resolve(1111)
      },1000)
    })
    
    const p2=new Promise((resolve)=>{
      setTimeout(()=>{
        resolve(2222)
      },2000)
    })
    
    const p3=new Promise((resolve)=>{
      setTimeout(()=>{
        resolve(3333)
      },3000)
    })
    // *all方法会产生一个新的Promise对象,这个新的Promise对象是由前面的所有的Promise来决定其状态
    // * 如果全部为fulfilled,则会执行then方法,如果有一个为rejected,则直接执行catch方法
    HYPromise.all([p1,p2,p3]).then(res=>{
      console.log("res:",res);
    }).catch(err=>{
      console.log("err:",err);
    })
    
    
    // * allSettled:它会等所有的Promise都有结果,然后再执行resolve方法,它是没有reject方法的执行
    // * 实现了all方法:
    
    HYPromise.allSettled([p1,p2,p3]).then(res=>{
      console.log("res:",res);
    }).catch(err=>{
      console.log("err:",err);
    })
     
    

    9. 类方法 race和any

    const PROMISE_STATUS_FULFILLED="fulfilled";
    const PROMISE_STATUS_PENDING="pending";
    const PROMISE_STATUS_REJECTED="rejected";
    
    // 工具函数
    
    function execFunctionWithCatchError(exeFn,value,resolve,reject){
      try{
        const result=exeFn(value);
        resolve(result);
      }catch(err){
        reject(err);
      }
    }
    class HYPromise{
      constructor(executor){
        this.status=PROMISE_STATUS_PENDING;
        this.value=undefined;
        this.reason=undefined;
        // this.onFulfilled=undefined;
        // this.onRejected=undefined;
        this.onFulfilledFns=[];
        this.onRejectedFns=[];
        const resolve=(value)=>{
          if(this.status==PROMISE_STATUS_PENDING){
            // * 原生执行then方法时是一个微任务
            queueMicrotask(()=>{
              if(this.status!==PROMISE_STATUS_PENDING) return; 
              this.status=PROMISE_STATUS_FULFILLED;
              this.value=value;
              //  * 执行then传入进来的回调函数
              // this.onFulfilled(this.value);
              this.onFulfilledFns.forEach(Fn=>{
                Fn(this.value);
              })
            })
          }
         
        }
    
        const reject=(reason)=>{
          if(this.status==PROMISE_STATUS_PENDING){
           queueMicrotask(()=>{
             if(this.status!==PROMISE_STATUS_PENDING) return; 
            this.status=PROMISE_STATUS_REJECTED;
            this.reason=reason;
            // * 执行then传入进来的第二个参数
            // this.onRejected(this.reason);
            this.onRejectedFns.forEach(Fn=>{
              Fn(this.reason);
            })
           })
    
         }
        }
        try{
        executor(resolve,reject)
        }catch(err){
          reject(err);
        }
        
      }
    
      then(onFulfilled,onRejected){
         onRejected=onRejected|| (err=>{ throw err});
         onFulfilled=onFulfilled|| (value=>value)
        return new HYPromise((resolve,reject)=>{
          if(this.status==PROMISE_STATUS_FULFILLED&&onFulfilled){
            execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
          }else if(this.status==PROMISE_STATUS_REJECTED&&onRejected){
            execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
          }else{
            if(onFulfilled)this.onFulfilledFns.push(()=>{
            execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
            });
            if(onRejected)this.onRejectedFns.push(()=>{
            execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
            });
          }
        })
       
      }
      catch(onRejected){
        return this.then(undefined,onRejected);
      }
    
      finally(onFinally){
        return this.then(()=>{
          onFinally();
        },()=>{
          onFinally();
        })
      }
      static resolve(value){
        return new HYPromise((resolve,reject)=>{
          resolve(value);
        })
      }
      static reject(reason){
        return new HYPromise((resolve,reject)=>{
          reject(reason);
        })
      }
      static all(promises){
        // * 问题关键:什么时候执行resolve,什么时候执行reject
       return new HYPromise((resolve,reject)=>{
         let values=[];
          promises.forEach(promise=>{
            promise.then(res=>{
               values.push(res);
               if(values.length==promises.length) resolve(values);
            }).catch(err=>{
               reject(err);
            })
          })
       })
      }
      static allSettled(promises){
        
        return new HYPromise((resolve)=>{
          let results=[];
          promises.forEach(promise=>{
            promise.then(res=>{
              results.push({status:PROMISE_STATUS_FULFILLED,value:res})
              if(results.length==promises.length)
              resolve(results);
            }).catch(err=>{
              results.push({status:PROMISE_STATUS_REJECTED,value:err})
              if(results.length==promises.length)
              resolve(results);
            })
          })
        })
      }
    
      static race(promises){
        return new HYPromise((resolve,reject)=>{
          promises.forEach(promise=>{
            // promise.then(res=>{
            //   resolve(res);
            // }).catch(err=>{
            //   reject(err);
            // })
            promise.then(resolve,reject)
          })
        })
      }
      static any(promises){
        // * resolve必须等待有一个成功的结果
        // * reject 所有的都失败才执行 reject
        return new HYPromise((resolve,reject)=>{
          let count=0;
          let reasons=[];
          promises.forEach(promise=>{
            promise.then(res=>{
              resolve(res)
            }).catch(err=>{
              reasons.push(err);
              if(reasons.length==promises.length){
                
                // reject(reasons)
                reject(new AggregateError(reasons," AggregateError: All promises were rejected"))
              }
            })
          })
        })
      }
    }
    
    // const p1=new Promise((resolve)=>{
    //   setTimeout(()=>{
    //     resolve(1111)
    //   },1000)
    // })
    
    // const p2=new Promise((resolve)=>{
    //   setTimeout(()=>{
    //     resolve(2222)
    //   },2000)
    // })
    
    // const p3=new Promise((resolve)=>{
    //   setTimeout(()=>{
    //     resolve(3333)
    //   },3000)
    // })
    
    // HYPromise.race([p1,p2,p3]).then(res=>{
    //   console.log("res:",res);
    // }).catch(err=>{
    //   console.log("err:",err);
    // })
    
    // * any方法
    const p1=new Promise((resolve,reject)=>{
      setTimeout(()=>{
        reject(1111)
      },1000)
    })
    
    const p2=new Promise((resolve,reject)=>{
      setTimeout(()=>{
        reject(2222)
      },2000)
    })
    
    const p3=new Promise((resolve,reject)=>{
      setTimeout(()=>{
        reject(3333)
      },3000)
    })
    
    HYPromise.any([p1,p2,p3]).then(res=>{
      console.log("res:",res);
    }).catch(err=>{
      console.log("err:",err.errors);
    })
    

    相关文章

      网友评论

        本文标题:JS 手写Promise

        本文链接:https://www.haomeiwen.com/subject/nrriurtx.html