前端面试题 - 102. 实现一个简单的Promise类,包括then和catch方法。

237 阅读1分钟

内置属性status的流转:初始化(resolve、reject)、then、catch。并记录value和reason

class Promise {
  constructor(executor) {
    // 更新状态和值。执行回调函数
    this.state = "pending";
    this.value = undefined;
    this.handlers = [];

    const resolve = (value) => {
      if (this.state === "pending") {
        this.state = "fulfilled";
        this.value = value;
        this.handlers.forEach((handler) => handler.onFulfilled(value));
      }
    };

    const reject = (reason) => {
      if (this.state === "pending") {
        this.state = "rejected";
        this.value = reason;
        this.handlers.forEach((handler) => handler.onRejected(reason));
      }
    };

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

  then(onFulfilled, onRejected) {
    // 返回一个Promise。定义个执行函数(resolve\reject\then)。下面就是根据三种状态去执行(有回调执行回调,没有就执行默认的,如果是pending就缓存执行方法)。
    return new Promise((resolve, reject) => {
      const handle = (handler) => {
        try {
          const result = handler(this.value);
          if (result instanceof Promise) {
            result.then(resolve, reject);
          } else {
            resolve(result);
          }
        } catch (error) {
          reject(error);
        }
      };

      if (this.state === "pending") {
        this.handlers.push({
          onFulfilled: (value) => {
            if (typeof onFulfilled === "function") {
              handle(onFulfilled);
            } else {
              resolve(value);
            }
          },
          onRejected: (reason) => {
            if (typeof onRejected === "function") {
              handle(onRejected);
            } else {
              reject(reason);
            }
          },
        });
      } else if (this.state === "fulfilled") {
        if (typeof onFulfilled === "function") {
          handle(onFulfilled);
        } else {
          resolve(this.value);
        }
      } else if (this.state === "rejected") {
        if (typeof onRejected === "function") {
          handle(onRejected);
        } else {
          reject(this.value);
        }
      }
    });
  }

  catch(onRejected) {
    // then只有reject
    return this.then(null, onRejected);
  }

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

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

  static all(promises) {
    return new Promise((resolve, reject) => {
      const results = [];
      let finishedCount = 0;

      promises.forEach((promise, index) => {
        promise.then((value) => {
          results[index] = value;
          finishedCount++;

          if (finishedCount === promises.length) {
            resolve(results);
          }
        }).catch((reason) => {
          reject(reason);
        });
      });
    });
  }

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