手写Promise

94 阅读3分钟

手写一个Promise(严格按照Promise/a+规范)

  1. 规范 Promise/A+
  2. Promise类的设计 Class HYpromise 3.构造函数的规划
class HYpromise{
  construrctor(executor)
  // 定义状态
  // 定义resolve reject回调
  // 使用resolve执行微任务队列 改变状态 获取value then传入执行成功回调
  // reject 执行微任务队列 改变状态 获取reason then传入失败回调
  //try catch 检测异常 
  excutor(resolve,reject)
  }
  }

4.then方法的实现

  class HYpromise{
    then(onFulfilled,onReject){
      this.onFulfilled=onFulfilled
      this.onReject=onReject
      1.判断onFulfilled,onReject 会给默认值
      2.返回Promise resolve/reject
      3.判断之前的promise状态是否确定
      onFulfilled,onReject直接执行(捕获异常)
      4.添加到数组push(()=>{执行onFulfilled/onReject 直接执行代码})
    }
  }

5.catch方法

    // 直接实现catch 给他一个返回值  因为调then 都会执行传入的函数
    return this.then(undefined, onRehected);
   }

6.finally

      class HYpromise{
       // 不会成功还是失败 他都会调用onFinally函数
    this.then(
      () => {
        onFinally();
      },
      () => {
        onFinally();
      }
    );
   }
   7.resolve/reject

  static resolve(value) {
    return new HYPromise(resolve => resolve(value));
  }

  static reject(reason) {
    return new HYPromise(reject => reject(reason));
  }

实现代码

// 手写Promise
// 需要按照Promise/A+

// Promise目前的状态 状态管理
const PROMISE_STATUS_PENDING = 'pending';
const PROMISE_STATUS_FULFILLED = 'fulfiled';
const PROMISE_STATUS_REJECT = 'reject';

// 工具函数 封装函数
function execFunctionWithCatchErrorFun(exeFn, value, resolve, reject) {
  try {
    const result = exeFn(value);
    resolve(result);
  } catch (error) {
    reject(error);
  }
}

class HYPromise {
  constructor(executor) {
    // 刚开始调用 是pending 初始值
    this.status = PROMISE_STATUS_PENDING;
    this.value = undefined;
    this.reason = undefined;
    // 2.所有的回调保存在一个数组里面 这样可以多次调用同一个promise
    this.onFulfilledFns = [];
    this.onRehectedFms = [];
    const resolve = value => {
      if (this.status === PROMISE_STATUS_PENDING) {
        // 1.利用event Loop的宏任务 微任务来 为了不堵塞主线程任务
        // setTimeout 是一个宏任务
        // 修改状态的需要在本轮的事件任务改
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return;
          this.status = PROMISE_STATUS_FULFILLED;
          // then接受的参数
          this.value = value;
          console.log('resolve被调用', value);
          // then传进来的回调函数
          // this.onFulfilled(this.value);
          // 2.执行加入数组的回调函数
          this.onFulfilledFns.forEach(fn => {
            fn(this.value);
          });
        }, 0);
      }
    };
    const reject = reason => {
      if (this.status === PROMISE_STATUS_PENDING) {
        // 2.因为promise本身就是一个微任务 所以不要给他加入宏任务,使用queueMicrotask把函数加入微任务里面 他也会延迟调用 他会在本轮的事件循环后调用
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return;
          this.reason = reason;
          this.status = PROMISE_STATUS_REJECT;
          console.log('reject被调用', reason);
          // this.onRehected(this.reason);

          // 2.执行加入数组的回调函数
          this.onRehectedFms.forEach(fn => {
            fn(this.reason);
          });
        });
      }
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRehected) {
    // 3. 当封装catch 时候会直接调用then方法 他就没有onRehected参数 这个时候直接抛出异常 这样会直接走本身的reject的catch方法
    // onRehected =
    //   onRehected === undefined
    //     ? err => {
    //         throw err;
    //       }
    //     : onRehected;
    onRehected =
      onRehected ||
      (err => {
        throw err;
      });

    onFulfilled =
      onFulfilled ||
      (value => {
        return value;
      });

    // 为了返回一个Promise 实现链式调用
    return new HYPromise((resolve, reject) => {
      // this.onFulfilled = onFulfilled;
      // this.onRehected = onRehected;

      // 2.如果当前已经有了状态  直接执行本次函数
      // 为了有延迟执行的then回调函数 更加严谨
      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
        // 因为链式调用 返回的都是resolve 也就是then的回调函数 只有当异常了 才会调reject
        // try {
        //   const value = onFulfilled(this.value);
        //   resolve(value);
        // } catch (error) {
        //   reject(error);
        // }
        // 3.使用封装函数
        execFunctionWithCatchErrorFun(onFulfilled, this.value, resolve, reject);
      }
      if (this.status === PROMISE_STATUS_REJECT && onRehected) {
        // 因为链式调用 返回的都是resolve 也就是then的回调函数 只有当异常了 才会调reject
        // try {
        //   const reason = onRehected(this.reason);
        //   resolve(reason);
        // } catch (error) {
        //   reject(error);
        // }
        // 3.使用封装函数
        execFunctionWithCatchErrorFun(onRehected, this.reason, resolve, reject);
      }

      // 2.then 多次调用 把所有的回调加入一个数组里面  如果当前状态时padding的话 加入数组
      if (this.status === PROMISE_STATUS_PENDING) {
        if (onFulfilled)
          this.onFulfilledFns.push(() => {
            // 返回一个函数 当函数执行的时候可以拿到函数值
            // try {
            //   const value = onFulfilled(this.value);
            //   resolve(value);
            // } catch (error) {
            //   reject(error);
            // }
            // 3.使用封装函数
            execFunctionWithCatchErrorFun(
              onFulfilled,
              this.value,
              resolve,
              reject
            );
          });
        if (onRehected)
          this.onRehectedFms.push(() => {
            // try {
            //   const reason = onRehected(this.reason);
            //   resolve(reason);
            // } catch (error) {
            //   reject(error);
            // }
            // 3.使用封装函数
            execFunctionWithCatchErrorFun(
              onRehected,
              this.reason,
              resolve,
              reject
            );
          });
      }
    });
  }
  catch(onRehected) {
    // 直接实现catch 给他一个返回值  因为调then 都会执行传入的函数
    return this.then(undefined, onRehected);
  }

  finally(onFinally) {
    // 不会成功还是失败 他都会调用onFinally函数
    this.then(
      () => {
        onFinally();
      },
      () => {
        onFinally();
      }
    );
  }

  static resolve(value) {
    return new HYPromise(resolve => resolve(value));
  }

  static reject(reason) {
    return new HYPromise(reject => reject(reason));
  }

  static all(promises) {
    return HYPromise((resolve, reject) => {
      const values = [];
      promises.forEach(promises => {
        promises.then(
          res => {
            values.push(res);
            if (values.length === promises.length) {
              resolve(values);
            }
          },
          err => {
            reject(err);
          }
        );
      });
    });
  }

  static allSettled(promises) {
    return HYPromise(resolve => {
      const values = [];
      promises.forEach(promises => {
        promises.then(
          res => {
            values.push({ status: PROMISE_STATUS_FULFILLED, value: res });
            if (values.length === promises.length) {
              resolve(values);
            }
          },
          err => {
            values.push({ status: PROMISE_STATUS_REJECT, value: err });
            if (values.length === promises.length) {
              resolve(values);
            }
          }
        );
      });
    });
  }

  static race(promises) {
    return HYPromise(resolve => {
      promises.forEach(promise => {
        // promises.then(
        //   res => {
        //     resolve(res);
        //   },
        //   err => {
        //     reject(err);
        //   }
        // );
        // 简写
        promise.then(resolve, reject);
      });
    });
  }
  static any(promises) {
    // 至少有一个成功的 resolve
    // 所有的都失败了 reject
    const reasons = [];
    return HYPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(resolve, err => {
          reasons.push(err);
          if (reasons.length === promises.length) {
            // 捕获异常是一个数组
            reject(new AggregateError(reasons));
          }
        });
      });
    });
  }
}

const promise = new HYPromise((resolve, reject) => {
  resolve(1111);
  reject(2222);
});

promise.then(
  res => {
    console.log(res);
  },
  err => {
    console.log(err);
  }
);