美文网首页
38.手写promise

38.手写promise

作者: 静昕妈妈芦培培 | 来源:发表于2021-11-26 15:06 被阅读0次

    promise规范:https://promisesaplus.com/

    手写promise-阶段1

    /**
     * 手写promise-实现阶段1:
     *  实现功能:
     *    1.在通过new HyPromise(executor)创建promise对象时,executor执行函数立即被调用
     *    2.executor函数有两个参数,resolve和reject,这两个参数都是回调函数
     *    3.promise有一个状态,可以取值'pending','fulfilled','rejected',
     *    4.promise对象初始状态为'pending',resolve回调函数执行,会把其状态改为'fulfilled',reject回调函数执行,会把其状态改为'rejected'
     *    5.一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态,即没有任何效果
     *    6.resolve回调函数执行时,接收一个参数value,reject回调函数执行时,接收一个参数reason
     *
     *
     */
    
    const PROMISE_STATUS_PENDING = "pending";
    const PROMISE_STATUS_FULFILLED = "fulfilled";
    const PROMISE_STATUS_REJECTED = "rejected";
    
    class HyPromise {
      constructor(executor) {
        //promise对象初始状态为'pending'
        this.status = PROMISE_STATUS_PENDING;
    
        const resolve = (value) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            //resolve回调函数执行,会把其状态改为'fulfilled'
            this.status = PROMISE_STATUS_FULFILLED;
            console.log("resolve回调函数被执行");
          }
        };
        const reject = (reason) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            //reject回调函数执行,会把其状态改为'rejected'
            this.status = PROMISE_STATUS_REJECTED;
            console.log("reject回调函数被执行");
          }
        };
        // executor执行函数在在通过new HyPromise(executor)创建promise对象时,立即被执行
        executor(resolve, reject);
      }
    }
    const promise = new HyPromise((resolve, reject) => {
      resolve(111);
      //reject('error msg')
    });
    
    
    

    手写promise-阶段2

    /**
     * 手写promise-实现阶段2:
     *  实现功能:
     *   7.每一个promise对象都有一个then方法,then方法执行时需要传入两个回调函数,onFulfilled,onRejected
     *      onFulfilled回调有一个参数value,onRejected回调函数有一个参数reason
     *   8.当resolve回调函数执行改变当前promise对象的状态为'fulfilled'后,会立即执行onFulfilled回调函数,并把resolve的参数value值作为参数传给onFulfilled函数
     *     当reject回调函数执行改变当前promise对象的状态为'rejected'后,会立即执行onRejected回调函数,并把reject的参数reason值作为参数传给onFulfilled函数
     *   9.then方法执行是在主线程中,如果resolve和reject方法执行也是在主线中的话,resolve和reject的执行实际早于then,
     *     那时onFulfilled和onRejected回调还没通过then传进去,在执行resolve或reject函数内部是要执行onFulfilled或onRejected函数的,那时就会报错
     *     所以,在resolve或reject函数内部对onFulfilled或onRejected函数的调用要在一个微任务中,这样then函数的执行时机就早于onFulfilled或onRejected函数的执行
     *   
     *
     */
    
    const PROMISE_STATUS_PENDING = "pending";
    const PROMISE_STATUS_FULFILLED = "fulfilled";
    const PROMISE_STATUS_REJECTED = "rejected";
    
    class HyPromise {
      constructor(executor) {
        //promise对象初始状态为'pending'
        this.status = PROMISE_STATUS_PENDING;
        this.onFulfilledFn = undefined;
        this.onRejectedFn = undefined;
    
        const resolve = (value) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            //resolve回调函数执行,会把其状态改为'fulfilled'
            this.status = PROMISE_STATUS_FULFILLED;
            console.log("resolve回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              this.onFulfilledFn(value);
            });
          }
        };
        const reject = (reason) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            //reject回调函数执行,会把其状态改为'rejected'
            this.status = PROMISE_STATUS_REJECTED;
            console.log("reject回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              this.onRejectedFn(reason);
            });
          }
        };
        // executor执行函数在在通过new HyPromise(executor)创建promise对象时,立即被执行
        executor(resolve, reject);
      }
    
      //在类的prototype原型对象上定义then方法
      then(onFulfilled, onRejected) {
        this.onFulfilledFn = onFulfilled;
        this.onRejectedFn = onRejected;
      }
    }
    const promise = new HyPromise((resolve, reject) => {
      resolve(111);
      reject('error msg')
    });
    
    promise.then(
      (res) => {
        console.log(res);
      },
      (err) => {
        console.log(err);
      }
    );
    
    

    手写promise-阶段3

    /**
     * 手写promise-实现阶段3:
     *  实现功能:
     *   10.promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
     *   11.假如把then方法的调用放到一个setTimeout定时器里,定时器的then方法执行时,
     *      已经对onFulfilledFns或onRejectedFns数组进行遍历,执行了里面存储的所有的onFulfilled或onRejected回调
     *      此时通过定时器里的then方法添加的onFulfilled或onRejected回调就不能被执行
     *      可以在then方法里增加一个判断,执行then时,当前对象的状态为pending,就把onFulfilled或onRejected回调添加到onFulfilledFns或onRejectedFns数组里,
     *      如果状态不为pending,就执行把传入的onFulfilled或onRejected回调执行了
     *   
     *   目前代码存在一个bug:因为resolve和reject里改变promise对象的状态放在了微任务中,造成在new promise对象时,如果resolve和reject都调用的话,
     *   resolve和reject函数中的微任务都会被添加,这是因为resolve和reject都是在主线程执行,此时promise的对象一直是pending,所以都添加到微任务中了
     */
    
    const PROMISE_STATUS_PENDING = "pending";
    const PROMISE_STATUS_FULFILLED = "fulfilled";
    const PROMISE_STATUS_REJECTED = "rejected";
    
    class HyPromise {
      constructor(executor) {
        //promise对象初始状态为'pending'
        this.status = PROMISE_STATUS_PENDING;
        this.onFulfilledFns = [];
        this.onRejectedFns = [];
        this.value = undefined;
        this.reason = undefined;
    
        const resolve = (value) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            this.value = value;
            console.log("resolve回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              //resolve回调函数执行,会把其状态改为'fulfilled'
              this.status = PROMISE_STATUS_FULFILLED;
              //promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
              this.onFulfilledFns.forEach((fn) => {
                fn(value);
              });
            });
          }
        };
        const reject = (reason) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            this.reason = reason;
            console.log("reject回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              //reject回调函数执行,会把其状态改为'rejected'
              this.status = PROMISE_STATUS_REJECTED;
              //promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
              this.onRejectedFns.forEach((fn) => {
                fn(reason);
              });
            });
          }
        };
        // executor执行函数在在通过new HyPromise(executor)创建promise对象时,立即被执行
        executor(resolve, reject);
      }
    
      //在类的prototype原型对象上定义then方法
      then(onFulfilled, onRejected) {
        //假如onFulfilled为null或undefined,给其一个默认函数
        onFulfilled = onFulfilled ?? ((value) => {});
        // 假如onFulfilled为一些基本数据类型,如'', 123, true,正则表达式,{name: 'why'},报错
        if (typeof onFulfilled !== "function") {
          throw new TypeError("onFulfilled must be a function");
        }
    
        //假如onRejected为null或undefined,给其一个默认函数
        onRejected = onRejected ?? ((reason) => {});
        // 假如onFulfilled为一些基本数据类型,如'', 123, true,正则表达式,{name: 'why'},报错
        if (typeof onRejected !== "function") {
          throw new TypeError("onRejected must be a function");
        }
    
        //执行then时,当前对象的状态为pending,就把onFulfilled或onRejected回调添加到onFulfilledFns或onRejectedFns数组里,
        //如果状态不为pending,就执行把传入的onFulfilled或onRejected回调执行了
        if (this.status === PROMISE_STATUS_PENDING) {
          this.onFulfilledFns.push(onFulfilled);
          this.onRejectedFns.push(onRejected);
        } else if (this.status === PROMISE_STATUS_FULFILLED) {
          onFulfilled(this.value);
        } else if (this.status === PROMISE_STATUS_REJECTED) {
          onRejected(this.reason);
        }
      }
    }
    const promise = new HyPromise((resolve, reject) => {
      resolve(111);
      // reject("error msg");
    });
    
    promise.then(
      (res) => {
        console.log("res1", res);
      },
      (err) => {
        console.log("err1", err);
      }
    );
    promise.then(
      (res) => {
        console.log("res2", res);
      },
      (err) => {
        console.log("err2", err);
      }
    );
    
    setTimeout(() => {
      promise.then(
        (res) => {
          console.log("res3", res);
        },
        (err) => {
          console.log("err3", err);
        }
      );
    }, 300);
    
    

    手写promise-阶段4

    /**
     * 手写promise-实现阶段3:
     *  实现功能:
     *   解决这个bug:因为resolve和reject里改变promise对象的状态放在了微任务中,造成在new promise对象时,如果resolve和reject都调用的话,
     *   resolve和reject函数中的微任务都会被添加,这是因为resolve和reject都是在主线程执行,此时promise的对象一直是pending,所以都添加到微任务中了
     *
     *   12.then方法执行返回一个新的promise对象newPromise,不管上一个promise的onFulfilled还是onRejected回调函数执行,newPromise的resolve都执行,
     *      执行时的参数为promise的onFulfilled或者onRejected回调函数执行的返回值,newPromise的状态都变为fulfilled,
     *      除非上一个promise的onFulfilled或者onRejected回调函数执行过程中抛出异常,newPromise的reject执行时的参数为此异常信息,
     *   13.exector函数执行如果抛出异常,promise对象的状态变为rejected,onRejected回调会被执行,参数为此异常信息
     *
     */
    
    const PROMISE_STATUS_PENDING = "pending";
    const PROMISE_STATUS_FULFILLED = "fulfilled";
    const PROMISE_STATUS_REJECTED = "rejected";
    
    function execFunctionWithCatchError(execFn, value, resolve, reject) {
      try {
        const result = execFn(value);
        resolve(result);
      } catch (error) {
        reject(error);
      }
    }
    class HyPromise {
      constructor(executor) {
        //promise对象初始状态为'pending'
        this.status = PROMISE_STATUS_PENDING;
        this.onFulfilledFns = [];
        this.onRejectedFns = [];
        this.value = undefined;
        this.reason = undefined;
    
        const resolve = (value) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            this.value = value;
            // console.log("resolve回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              //解决这个bug:因为resolve和reject里改变promise对象的状态放在了微任务中,造成在new promise对象时,如果resolve和reject都调用的话,
              //resolve和reject函数中的微任务都会被添加,这是因为resolve和reject都是在主线程执行,此时promise的对象一直是pending,所以都添加到微任务中了
              if (this.status !== PROMISE_STATUS_PENDING) return;
              //resolve回调函数执行,会把其状态改为'fulfilled'
              this.status = PROMISE_STATUS_FULFILLED;
              //promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
              this.onFulfilledFns.forEach((fn) => {
                fn(value);
              });
            });
          }
        };
        const reject = (reason) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            this.reason = reason;
            // console.log("reject回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              //解决这个bug:因为resolve和reject里改变promise对象的状态放在了微任务中,造成在new promise对象时,如果resolve和reject都调用的话,
              //resolve和reject函数中的微任务都会被添加,这是因为resolve和reject都是在主线程执行,此时promise的对象一直是pending,所以都添加到微任务中了
              if (this.status !== PROMISE_STATUS_PENDING) return;
              //reject回调函数执行,会把其状态改为'rejected'
              this.status = PROMISE_STATUS_REJECTED;
              //promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
              this.onRejectedFns.forEach((fn) => {
                fn(reason);
              });
            });
          }
        };
        // executor执行函数在在通过new HyPromise(executor)创建promise对象时,立即被执行
        try {
          executor(resolve, reject);
        } catch (error) {
          //exector函数执行如果抛出异常,promise对象的状态变为rejected,onRejected回调会被执行,参数为此异常信息
          reject(error);
        }
      }
    
      //在类的prototype原型对象上定义then方法
      then(onFulfilled, onRejected) {
        //假如onFulfilled为null或undefined,给其一个默认函数
        onFulfilled = onFulfilled ?? ((value) => {});
        // 假如onFulfilled为一些基本数据类型,如'', 123, true,正则表达式,{name: 'why'},报错
        if (typeof onFulfilled !== "function") {
          throw new TypeError("onFulfilled must be a function");
        }
    
        //假如onRejected为null或undefined,给其一个默认函数
        onRejected = onRejected ?? ((reason) => {});
        // 假如onFulfilled为一些基本数据类型,如'', 123, true,正则表达式,{name: 'why'},报错
        if (typeof onRejected !== "function") {
          throw new TypeError("onRejected must be a function");
        }
    
        //then方法执行返回一个新的promise对象newPromise,不管上一个promise的onFulfilled还是onRejected回调函数执行,newPromise的resolve都执行,
        //执行时的参数为promise的onFulfilled或者onRejected回调函数执行的返回值,newPromise的状态都变为fulfilled,
        //除非上一个promise的onFulfilled或者onRejected回调函数执行过程中抛出异常,newPromise的reject执行时的参数为此异常信息,
        return new HyPromise((resolve, reject) => {
          //执行then时,当前对象的状态为pending,就把onFulfilled或onRejected回调添加到onFulfilledFns或onRejectedFns数组里,
          //如果状态不为pending,就执行把传入的onFulfilled或onRejected回调执行了
          if (this.status === PROMISE_STATUS_PENDING) {
            this.onFulfilledFns.push((value) => {
              execFunctionWithCatchError(onFulfilled, value, resolve, reject);
            });
            this.onRejectedFns.push((reason) => {
              execFunctionWithCatchError(onRejected, reason, resolve, reject);
            });
          } else if (this.status === PROMISE_STATUS_FULFILLED) {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject);
          } else if (this.status === PROMISE_STATUS_REJECTED) {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject);
          }
        });
      }
    }
    const promise = new HyPromise((resolve, reject) => {
      // resolve(111);
      // reject("error msg");
      throw new Error(' executor error')
    });
    
    promise
      .then(
        (res) => {
          console.log("res1", res);
          return "aaa";
        },
        (err) => {
          console.log("err1", err);
          return "bbb";
          // throw new Error('error')
        }
      )
      .then(
        (res) => {
          console.log("res2", res);
        },
        (err) => {
          console.log("err2", err);
        }
      );
    
    // promise.then(
    //   (res) => {
    //     console.log("res2", res);
    //   },
    //   (err) => {
    //     console.log("err2", err);
    //   }
    // );
    
    // setTimeout(() => {
    //   promise.then(
    //     (res) => {
    //       console.log("res3", res);
    //     },
    //     (err) => {
    //       console.log("err3", err);
    //     }
    //   );
    // }, 300);
    
    

    手写promise-阶段5

    /**
     * 手写promise-实现阶段3:
     *  实现功能:
     *   14.如果promise的onFulfiled或onRejected回调的返回值:
     *      是一个普通值或对象,直接作为参数传给thenPromise的resolve
     *      是一个新的promise对象,thenPromise对象的状态由这个新的promise对象决定
     *      是一个实现了then方法的对象obj,then方法接收两个回调参数resolve,reject,
     *          obj的then方法会立即被执行,
     *          在then方法中执行了resolve,thenPromise对象的状态变为fulfilled,onFulfilled回调被执行,参数为then方法内部执行的resolve的参数
     *   15.实现promise对象的catch方法
     *        如果第一个promise对象的状态变为了rejected,而他的then方法执行时没传onRejected,
     *        此时then方法返回的thenPromise对象的状态也被改为rejected,thenPromise对象的onRejected回调被调用,参数为第一个promise对象被拒的原因
     *
     *        如果第一个promise对象的状态变为了fulfilled,而他的then方法执行时没传onFulfilled,
     *        此时then方法返回的thenPromise对象的状态也被改为fulfilled,thenPromise对象的onFulfilled回调被调用,参数为第一个promise对象resolve的参数
     *
     *        catch方法调用也返回一个新的promise对象
     *   16.实现promise对象的finally方法
     *        不管promise对象的状态变为fulfilled或rejected,finally传入的回调都会被执行
     *        finally没有参数
     *
     */
    
    const PROMISE_STATUS_PENDING = "pending";
    const PROMISE_STATUS_FULFILLED = "fulfilled";
    const PROMISE_STATUS_REJECTED = "rejected";
    
    function execFunctionWithCatchError(execFn, value, resolve, reject) {
      try {
        const result = execFn(value);
        //onFulfilled或onRejected函数的返回值为一个新的promise对象
        if (result instanceof HyPromise) {
          result.then(
            (res) => {
              resolve(res);
            },
            (err) => {
              reject(err);
            }
          );
        } else if (
          //onFulfilled或onRejected函数的返回值为一个实现了then方法的对象
          typeof result === "object" &&
          typeof result.then === "function"
        ) {
          result.then(resolve, reject);
        } else {
          ////onFulfilled或onRejected函数的返回值为一个普通值或对象
          resolve(result);
        }
      } catch (error) {
        reject(error);
      }
    }
    class HyPromise {
      constructor(executor) {
        //promise对象初始状态为'pending'
        this.status = PROMISE_STATUS_PENDING;
        this.onFulfilledFns = [];
        this.onRejectedFns = [];
        this.value = undefined;
        this.reason = undefined;
    
        const resolve = (value) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            this.value = value;
            // console.log("resolve回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              //解决这个bug:因为resolve和reject里改变promise对象的状态放在了微任务中,造成在new promise对象时,如果resolve和reject都调用的话,
              //resolve和reject函数中的微任务都会被添加,这是因为resolve和reject都是在主线程执行,此时promise的对象一直是pending,所以都添加到微任务中了
              if (this.status !== PROMISE_STATUS_PENDING) return;
              //resolve回调函数执行,会把其状态改为'fulfilled'
              this.status = PROMISE_STATUS_FULFILLED;
              //promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
              this.onFulfilledFns.forEach((fn) => {
                fn(value);
              });
            });
          }
        };
        const reject = (reason) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            this.reason = reason;
            // console.log("reject回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              //解决这个bug:因为resolve和reject里改变promise对象的状态放在了微任务中,造成在new promise对象时,如果resolve和reject都调用的话,
              //resolve和reject函数中的微任务都会被添加,这是因为resolve和reject都是在主线程执行,此时promise的对象一直是pending,所以都添加到微任务中了
              if (this.status !== PROMISE_STATUS_PENDING) return;
              //reject回调函数执行,会把其状态改为'rejected'
              this.status = PROMISE_STATUS_REJECTED;
              //promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
              this.onRejectedFns.forEach((fn) => {
                fn(reason);
              });
            });
          }
        };
        // executor执行函数在在通过new HyPromise(executor)创建promise对象时,立即被执行
        try {
          executor(resolve, reject);
        } catch (error) {
          //exector函数执行如果抛出异常,promise对象的状态变为rejected,onRejected回调会被执行,参数为此异常信息
          reject(error);
        }
      }
    
      //在类的prototype原型对象上定义then方法
      then(onFulfilled, onRejected) {
        //假如onFulfilled为null或undefined,给其一个默认函数
        onFulfilled =
          onFulfilled ??
          ((value) => {
            //如果第一个promise对象的状态变为了fulfilled,而他的then方法执行时没传onFulfilled,
            //此时then方法返回的thenPromise对象的状态也被改为fulfilled,thenPromise对象的onFulfilled回调被调用,参数为第一个promise对象resolve的参数
            return value;
          });
        // 假如onFulfilled为一些基本数据类型,如'', 123, true,正则表达式,{name: 'why'},报错
        if (typeof onFulfilled !== "function") {
          throw new TypeError("onFulfilled must be a function");
        }
    
        //假如onRejected为null或undefined,给其一个默认函数
        onRejected =
          onRejected ??
          ((reason) => {
            //实现promise对象的catch方法
            //如果第一个promise对象的状态变为了rejected,而他的then方法执行时没传onRejected,
            //此时then方法返回的thenPromise对象的状态也被改为rejected,thenPromise对象的onRejected回调被调用,参数为第一个promise对象被拒的原因
            throw new Error(reason);
          });
        // 假如onFulfilled为一些基本数据类型,如'', 123, true,正则表达式,{name: 'why'},报错
        if (typeof onRejected !== "function") {
          throw new TypeError("onRejected must be a function");
        }
    
        //then方法执行返回一个新的promise对象newPromise,不管上一个promise的onFulfilled还是onRejected回调函数执行,newPromise的resolve都执行,
        //执行时的参数为promise的onFulfilled或者onRejected回调函数执行的返回值,newPromise的状态都变为fulfilled,
        //除非上一个promise的onFulfilled或者onRejected回调函数执行过程中抛出异常,newPromise的reject执行时的参数为此异常信息,
        return new HyPromise((resolve, reject) => {
          //执行then时,当前对象的状态为pending,就把onFulfilled或onRejected回调添加到onFulfilledFns或onRejectedFns数组里,
          //如果状态不为pending,就执行把传入的onFulfilled或onRejected回调执行了
          if (this.status === PROMISE_STATUS_PENDING) {
            this.onFulfilledFns.push((value) => {
              execFunctionWithCatchError(onFulfilled, value, resolve, reject);
            });
            this.onRejectedFns.push((reason) => {
              execFunctionWithCatchError(onRejected, reason, resolve, reject);
            });
          } else if (this.status === PROMISE_STATUS_FULFILLED) {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject);
          } else if (this.status === PROMISE_STATUS_REJECTED) {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject);
          }
        });
      }
      catch(onRejected) {
        return this.then(undefined, onRejected);
      }
      finally(onFinally) {
        return this.then(
          (res) => {
            onFinally();
          },
          (err) => {
            onFinally();
          }
        );
      }
    }
    const promise = new HyPromise((resolve, reject) => {
      resolve(111);
      // reject("error msg");
      // throw new Error(" executor error");
    });
    
    // promise
    //   .then(
    //     (res) => {
    //       console.log("res1", res);
    //       return 111;
    //     },
    //     (err) => {
    //       console.log("err1", err);
    //       return "bbb";
    //     }
    //   )
    //   .catch((err) => {
    //     console.log("err2", err);
    //   })
    //   .finally(() => {
    //     console.log("finally");
    //   });
    
    promise
      .catch((err) => {
        console.log("err1", err);
      })
      .then(
        (res) => {
          console.log("res2", res);
          return 111;
        },
        (err) => {
          console.log("err2", err);
          return "bbb";
        }
      )
      .finally(() => {
        console.log("finally");
      });
    
    

    手写promise-阶段6

    /**
     * 手写promise-实现阶段3:
     *  实现功能:
     *    Promise类方法resolve方法
     *    Promise类方法reject方法
     *    Promise类方法all方法
     *        参数为一个数组,如果数组的某个元素不是promise对象,则把其转换为resolve此元素的promise对象,即使此元素重新赋值为 Promise.resolve(此元素)
     *        返回一个新的promise对象allPromise,
     *        只有参数数组中的所有promise对象的状态都变为fulfilled,allPromise的状态才变为fulfilled,
     *        allPromise对象的resolve回到的参数是按照数组中promise对象状态改变的先后顺序,存储每个promise对象的结果的数组
     *    Promise类方法allSettled方法
     *        参数为一个数组,如果数组的某个元素不是promise对象,则把其转换为resolve此元素的promise对象,即使此元素重新赋值为 Promise.resolve(此元素)
     *        返回一个新的promise对象allSettledPromise,
     *        当arr中所有的promise对象的状态都敲定后,不管是变为fulfilled还是rejected,allSettledPromise对象的状态都会变为fulfilled,执行resolved回调,
     *        resolved回调的参数为一个数组,是按照数组中promise对象状态改变的先后顺序,返回每个promise对象的结果,
     *        数组中每个元素为一个对象,这个对象有两个属性,status和value/reason
     *        status为这个promise对象的状态,value为这个对象被对象的结果,reason为被拒绝的原因
     *    Promise类方法race方法
     *        参数为一个数组,如果数组的某个元素不是promise对象,则把其转换为resolve此元素的promise对象,即使此元素重新赋值为 Promise.resolve(此元素)
     *        返回一个新的promise对象racePromise,
     *        当前promise对象的状态由数组中第一个敲定状态的promise对象决定
     *    Promise.any(arr)
     *        参数是一个数组
     *        数组的元素建议是一个promise对象,如果不是,会使用Promise.resolve把其转为promise对象
     *        any方法执行返回一个新的promise对象anyPromise,
     *        只要arr中一个的promise对象的状态变为了fulfilled,anyPromise对象的状态都会变为fulfilled,执行resolved回调,
     *        resolved回调的参数为状态首先变为fulfilled的promise对象的resolve值,
     *        如果数组中所有的promise对象最终都变为rejected,anyPromise对象的状态都会变为rejected,执行rejected回调,
     *        rejected回调的参数为一个合计错误aggregateError,可以通过aggregateError.errors获得一个存储着所有promise被拒原因的数组
     *
     */
    
    const PROMISE_STATUS_PENDING = "pending";
    const PROMISE_STATUS_FULFILLED = "fulfilled";
    const PROMISE_STATUS_REJECTED = "rejected";
    
    function execFunctionWithCatchError(execFn, value, resolve, reject) {
      try {
        const result = execFn(value);
        //onFulfilled或onRejected函数的返回值为一个新的promise对象
        if (result instanceof HyPromise) {
          result.then(
            (res) => {
              resolve(res);
            },
            (err) => {
              reject(err);
            }
          );
        } else if (
          //onFulfilled或onRejected函数的返回值为一个实现了then方法的对象
          typeof result === "object" &&
          typeof result.then === "function"
        ) {
          result.then(resolve, reject);
        } else {
          ////onFulfilled或onRejected函数的返回值为一个普通值或对象
          resolve(result);
        }
      } catch (error) {
        reject(error);
      }
    }
    class HyPromise {
      constructor(executor) {
        //promise对象初始状态为'pending'
        this.status = PROMISE_STATUS_PENDING;
        this.onFulfilledFns = [];
        this.onRejectedFns = [];
        this.value = undefined;
        this.reason = undefined;
    
        const resolve = (value) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            this.value = value;
            // console.log("resolve回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              //解决这个bug:因为resolve和reject里改变promise对象的状态放在了微任务中,造成在new promise对象时,如果resolve和reject都调用的话,
              //resolve和reject函数中的微任务都会被添加,这是因为resolve和reject都是在主线程执行,此时promise的对象一直是pending,所以都添加到微任务中了
              if (this.status !== PROMISE_STATUS_PENDING) return;
              //resolve回调函数执行,会把其状态改为'fulfilled'
              this.status = PROMISE_STATUS_FULFILLED;
              //promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
              this.onFulfilledFns.forEach((fn) => {
                fn(value);
              });
            });
          }
        };
        const reject = (reason) => {
          //一旦promise对象的状态被修改为'fulfilled'或'rejected',再执行resolve或reject回调函数不会再改变其状态
          if (this.status === PROMISE_STATUS_PENDING) {
            this.reason = reason;
            // console.log("reject回调函数被执行");
    
            //创建一个微任务中,让onFulfilled或onRejected函数的执行时机晚于then函数的执行
            queueMicrotask(() => {
              //解决这个bug:因为resolve和reject里改变promise对象的状态放在了微任务中,造成在new promise对象时,如果resolve和reject都调用的话,
              //resolve和reject函数中的微任务都会被添加,这是因为resolve和reject都是在主线程执行,此时promise的对象一直是pending,所以都添加到微任务中了
              if (this.status !== PROMISE_STATUS_PENDING) return;
              //reject回调函数执行,会把其状态改为'rejected'
              this.status = PROMISE_STATUS_REJECTED;
              //promise对象的then方法可以多次调用,并且多次调用传入的多个onFulfilled或onRejected函数,在resolve或reject函数调用时,都会依次调用
              this.onRejectedFns.forEach((fn) => {
                fn(reason);
              });
            });
          }
        };
        // executor执行函数在在通过new HyPromise(executor)创建promise对象时,立即被执行
        try {
          executor(resolve, reject);
        } catch (error) {
          //exector函数执行如果抛出异常,promise对象的状态变为rejected,onRejected回调会被执行,参数为此异常信息
          reject(error);
        }
      }
    
      //在类的prototype原型对象上定义then方法
      then(onFulfilled, onRejected) {
        //假如onFulfilled为null或undefined,给其一个默认函数
        onFulfilled =
          onFulfilled ??
          ((value) => {
            //如果第一个promise对象的状态变为了fulfilled,而他的then方法执行时没传onFulfilled,
            //此时then方法返回的thenPromise对象的状态也被改为fulfilled,thenPromise对象的onFulfilled回调被调用,参数为第一个promise对象resolve的参数
            return value;
          });
        // 假如onFulfilled为一些基本数据类型,如'', 123, true,正则表达式,{name: 'why'},报错
        if (typeof onFulfilled !== "function") {
          throw new TypeError("onFulfilled must be a function");
        }
    
        //假如onRejected为null或undefined,给其一个默认函数
        onRejected =
          onRejected ??
          ((reason) => {
            //实现promise对象的catch方法
            //如果第一个promise对象的状态变为了rejected,而他的then方法执行时没传onRejected,
            //此时then方法返回的thenPromise对象的状态也被改为rejected,thenPromise对象的onRejected回调被调用,参数为第一个promise对象被拒的原因
            if (reason instanceof AggregateError) {
              //为了解决Promise类的any方法返回的promise对象状态变为rejected时,在catch中没法获取err.erros的问题
              throw new AggregateError(reason.errors);
            } else {
              throw new Error(reason);
            }
          });
        // 假如onFulfilled为一些基本数据类型,如'', 123, true,正则表达式,{name: 'why'},报错
        if (typeof onRejected !== "function") {
          throw new TypeError("onRejected must be a function");
        }
    
        //then方法执行返回一个新的promise对象newPromise,不管上一个promise的onFulfilled还是onRejected回调函数执行,newPromise的resolve都执行,
        //执行时的参数为promise的onFulfilled或者onRejected回调函数执行的返回值,newPromise的状态都变为fulfilled,
        //除非上一个promise的onFulfilled或者onRejected回调函数执行过程中抛出异常,newPromise的reject执行时的参数为此异常信息,
        return new HyPromise((resolve, reject) => {
          //执行then时,当前对象的状态为pending,就把onFulfilled或onRejected回调添加到onFulfilledFns或onRejectedFns数组里,
          //如果状态不为pending,就执行把传入的onFulfilled或onRejected回调执行了
          if (this.status === PROMISE_STATUS_PENDING) {
            this.onFulfilledFns.push((value) => {
              execFunctionWithCatchError(onFulfilled, value, resolve, reject);
            });
            this.onRejectedFns.push((reason) => {
              execFunctionWithCatchError(onRejected, reason, resolve, reject);
            });
          } else if (this.status === PROMISE_STATUS_FULFILLED) {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject);
          } else if (this.status === PROMISE_STATUS_REJECTED) {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject);
          }
        });
      }
      catch(onRejected) {
        return this.then(undefined, onRejected);
      }
      finally(onFinally) {
        return this.then(
          (res) => {
            onFinally();
          },
          (err) => {
            onFinally();
          }
        );
      }
    
      static resolve(value) {
        return new HyPromise((resolve, reject) => {
          resolve(value);
        });
      }
    
      static reject(reason) {
        return new HyPromise((resolve, reject) => {
          reject(reason);
        });
      }
    
      static all(promiseArr) {
        return new HyPromise((resolve, reject) => {
          const values = [];
          promiseArr.forEach((promise) => {
            if (!(promise instanceof HyPromise)) {
              promise = HyPromise.resolve(promise);
            }
            promise.then(
              (res) => {
                values.push(res);
                if (values.length === promiseArr.length) {
                  resolve(values);
                }
              },
              (err) => {
                reject(err);
              }
            );
          });
        });
      }
      static allSettled(promiseArr) {
        return new HyPromise((resolve, reject) => {
          const values = [];
          promiseArr.forEach((promise) => {
            if (!(promise instanceof HyPromise)) {
              promise = HyPromise.resolve(promise);
            }
            promise.then(
              (res) => {
                values.push({
                  status: PROMISE_STATUS_FULFILLED,
                  value: res,
                });
                if (values.length === promiseArr.length) {
                  resolve(values);
                }
              },
              (err) => {
                values.push({
                  status: PROMISE_STATUS_REJECTED,
                  reason: err,
                });
                if (values.length === promiseArr.length) {
                  resolve(values);
                }
              }
            );
          });
        });
      }
      static race(promiseArr) {
        return new HyPromise((resolve, reject) => {
          promiseArr.forEach((promise) => {
            if (!(promise instanceof HyPromise)) {
              promise = HyPromise.resolve(promise);
            }
            promise.then(resolve, reject);
          });
        });
      }
    
      static any(promiseArr) {
        return new HyPromise((resolve, reject) => {
          const reasons = [];
          promiseArr.forEach((promise) => {
            if (!(promise instanceof HyPromise)) {
              promise = HyPromise.resolve(promise);
            }
            promise.then(resolve, (err) => {
              reasons.push(err);
              if (reasons.length === promiseArr.length) {
                reject(new AggregateError(reasons));
              }
            });
          });
        });
      }
    }
    
    HyPromise.resolve(111).then((res) => {
      console.log(res);
    });
    HyPromise.reject(222).catch((err) => {
      console.log(err);
    });
    
    const p1 = new HyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve(111);
      }, 100);
    });
    
    const p2 = new HyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve(222);
      }, 200);
    });
    
    const p3 = new HyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve(333);
      }, 300);
    });
    
    const p4 = new HyPromise((resolve, reject) => {
      setTimeout(() => {
        reject("error msg");
      }, 300);
    });
    const p5 = new HyPromise((resolve, reject) => {
      setTimeout(() => {
        reject("error error");
      }, 300);
    });
    HyPromise.all([p2, p1, p3, "aaa", "111"])
      .then((res) => {
        console.log(res);
      })
      .catch((err) => {
        console.log(err);
      });
    
    HyPromise.allSettled([p2, p1, p3, p4, p5, "aaa", "111"]).then((res) => {
      console.log(res);
    });
    
    HyPromise.any([p5, p4]).then(
      (res) => {
        console.log(666, res);
      },
      (err) => {
        // console.log(err instanceof AggregateError);
        console.log(555, err.errors);
      }
    );
    
    HyPromise.any([p5, p4])
      .then((res) => {
        console.log(666, res);
      })
      .catch((err) => {
        console.log(554, err.errors);
      });
    
    

    非常感谢王红元老师的深入JavaScript高级语法让我学习到很多 JavaScript 的知识

    相关文章

      网友评论

          本文标题:38.手写promise

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