使用 class 实现 Promise

说明

使用 class动手实现了一遍 Promise

模仿: https://github.com/ydiguo/Promise (内含大量注释🤗)

使用 promises-aplus-tests 检验通过

仓库: MyPromise

代码

const PENDING_STATE = "pending";
const FULFILLED_STATE = "fulfilled";
const REJECTED_STATE = "rejected";

const isFunction = function (fun) {
  return typeof fun === "function";
};

const isObject = function (value) {
  return value && typeof value === "object";
};

class Mypromsie {
  constructor(executor) {
    if (!this || this.constructor !== Mypromsie) {
      throw new TypeError("Promise must be called with new");
    }

    if (!isFunction(executor)) {
      throw new TypeError("Promise constructor's argument must be a function");
    }

    this.state = PENDING_STATE;
    this.value = undefined;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      resolutionProcedure(this, value);
    };

    const reject = (reason) => {
      if (this.state === PENDING_STATE) {
        this.state = REJECTED_STATE;
        this.value = reason;

        this.onRejectedCallbacks.forEach((callback) => callback());
      }
    };

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }

    const resolutionProcedure = (promise, x) => {
      if (promise === x) {
        return reject(new TypeError("Promise can not resolved with it seft"));
      }

      if (x instanceof Mypromsie) {
        return x.then(resolve, reject);
      }

      if (isObject(x) || isFunction(x)) {
        let called = false;
        try {
          let then = x.then;

          if (isFunction(then)) {
            then.call(
              x,
              (y) => {
                if (called) return;
                called = true;
                resolutionProcedure(promise, y);
              },
              (error) => {
                if (called) return;
                called = true;
                reject(error);
              }
            );
            return;
          }
        } catch (error) {
          if (called) return;
          called = true;
          reject(error);
        }
      }

      if (promise.state === PENDING_STATE) {
        promise.state = FULFILLED_STATE;
        promise.value = x;

        promise.onFulfilledCallbacks.forEach((callback) => callback());
      }
    };
  }

  then(onFulfilled, onRejected) {
    onFulfilled = isFunction(onFulfilled) ? onFulfilled : (value) => value;
    onRejected = isFunction(onRejected)
      ? onRejected
      : (error) => {
          throw error;
        };

    const promise2 = new Mypromsie((resolve, reject) => {
      const wrapOnFulfilled = () => {
        setTimeout(() => {
          try {
            const x = onFulfilled(this.value);
            resolve(x);
          } catch (error) {
            reject(error);
          }
        }, 0);
      };
      const wrapOnRejected = () => {
        setTimeout(() => {
          try {
            const x = onRejected(this.value);
            resolve(x);
          } catch (error) {
            reject(error);
          }
        }, 0);
      };

      if (this.state === FULFILLED_STATE) {
        wrapOnFulfilled();
      } else if (this.state === REJECTED_STATE) {
        wrapOnRejected();
      } else {
        this.onFulfilledCallbacks.push(wrapOnFulfilled);
        this.onRejectedCallbacks.push(wrapOnRejected);
      }
    });

    return promise2;
  }

  catch(callback) {
    return this.then(null, callback);
  }

  finally(callback) {
    return this.then(
      (data) => {
        callback();
        return data;
      },
      (error) => {
        callback();
        throw error;
      }
    );
  }

  static resolve(value) {
    return value instanceof Mypromsie
      ? value
      : new Mypromsie((resolve) => resolve(value));
  }

  static reject(reason) {
    return new Mypromsie((resolve, reject) => reject(reason));
  }

  static race(promises) {
    return new Mypromsie((resolve, reject) => {
      promises.forEach((promise) =>
        Mypromsie.resolve(promise).then(resolve, rejec)
      );
    });
  }

  static all(promises) {
    return new Mypromsie((resolve, reject) => {
      let result = [];
      let resolveCount = 0;
      const len = promises.length;
      if (!len) {
        resolve([]);
      }

      for (let index = 0; index < len; index++) {
        Mypromsie.resolve(promises[index]).then(
          (data) => {
            result[index] = data;
            if (++resolveCount === len) {
              resolve(result);
            }
          },
          (error) => {
            reject(error);
          }
        );
      }
    });
  }

  static allSettled(promises) {
    return new Mypromsie((resolve, reject) => {
      let result = [];
      let resolveCount = 0;
      const len = promises.length;
      if (!len) {
        resolve([]);
      }

      for (let index = 0; index < len; index++) {
        Mypromsie.resolve(promises[index]).then(
          (data) => {
            result[index] = {
              status: FULFILLED_STATE,
              value: data,
            };
            if (++resolveCount === len) {
              resolve(result);
            }
          },
          (error) => {
            result[index] = {
              status: REJECTED_STATE,
              value: error,
            };
            if (++resolveCount === len) {
              resolve(result);
            }
          }
        );
      }
    });
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_pengliang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值