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

    基本定义 Promise 对象用于表示一个异步操作的最终完成或失败的状态, 并返回相应的结果值; Promise ...

  • JS 手写Promise

    二、手写Promise 1.Promise的设计和构造方法 2.then方法的设计 3.then方法的优化一 实现...

  • 「超全」手写Promise的相关方法

    原文发布在:手写Promise的相关方法。 摘要 Promise 作为 JS 社区的异步解决方案,为开发者提供了....

  • 手写Promise

    手写 Promise 我们会通过手写一个符合 Promise/A+ 规范的 Promise 来深入理解它,并且手写...

  • 函数式编程与Js异步编程、手写Promise(Day01)

    Part1 · JavaScript【深度剖析】 函数式编程与Js异步编程、手写Promise 文章说明:本专栏内...

  • 1-1作业参考答案

    模块一:函数式编程与 JS 异步编程、手写 Promise参考答案 简答题 一、谈谈你是如何理解 JS 异步编程的...

  • 59.JS->手写Promise

    day11:跟着训练营第一个手写promise注意点:1.new Promise参数里面的回调函数必传->首先定义...

  • 手写 Promise 系列 --- 3

    在前两篇(手写 Promise 系列 --- 1)和(手写 Promise 系列 ---2) 中,达成了3个目标 ...

  • 手写代码系列

    深拷贝 html转码 手写promise.all 有哪些实现数组扁平化的方法 原生js 运用flat方法 redu...

  • 手写Promise

    $ 正常的promise用法   $ 手写的Promise   # 测试可行性

网友评论

    本文标题:JS 手写Promise

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