美文网首页
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

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

  • 手写Promise

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

  • 手写 Promise 系列 --- 3

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

  • 手写Promise

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

  • 手写promise

    手写promise 带大家手写一个 promis。在手写之前我会先简单介绍一下为什么要使用promise、prom...

  • 纯手写实现自己的nodejs promise 库

    纯手写实现自己的nodejs promise 库什么是Promise?promise 链Async/Await后续...

  • 手写基础 promise

    1. 前言 玩下吧 手写 promise,看看能写成啥样 2. promise 基础结构 3. 手写`promi...

  • 手写 Promise

    一、Promise 是一个异步操作返回的对象,用来传递异步操作的消息。 Promise 介绍和使用详见: 认识并使...

  • 手写Promise

  • 手写Promise

    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。 这篇博客有关于P...

网友评论

      本文标题:38.手写promise

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