MyPromise

78 阅读3分钟

promise 是解决异步编程的一种方案,采用了状态编程的模式,通过注册 then 回调的方法,让异步代码可以一步一步执行,具体的细节请看代码:

const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'

class MyPromise {
  constructor(callback) {
    this.state = PENDING; // 定义 Promise 的状态,初始状态为 PENDING
    this.value = undefined; // 存储 Promise 的结果值
    this.callbacks = []; // 存储回调函数的数组

    // resolve 函数用于将 Promise 的状态设置为 RESOLVED,并执行相应的回调函数
    const resolve = (value) => {
      if (this.state === PENDING) {
        this.state = RESOLVED; // 将状态设置为 RESOLVED
        this.value = value; // 存储 Promise 的结果值
        this.scheduleCallbacks(); // 执行存储的回调函数
      }
    };

    // reject 函数用于将 Promise 的状态设置为 REJECTED,并执行相应的回调函数
    const reject = (reason) => {
      if (this.state === PENDING) {
        this.state = REJECTED; // 将状态设置为 REJECTED
        this.value = reason; // 存储 Promise 的结果值(错误原因)
        this.scheduleCallbacks(); // 执行存储的回调函数
      }
    };

    try {
      callback(resolve, reject); // 执行用户传入的回调函数
    } catch (err) {
      reject(err); // 如果回调函数执行出错,则将 Promise 的状态设置为 REJECTED
    }
  }
  // scheduleCallbacks 函数用于将回调函数的执行推迟到微任务队列中
  scheduleCallbacks() {
    queueMicrotask(() => {
      this.callbacks.forEach(callback => {
        this.executeCallback(callback);
      });
    });
  }
  // executeCallback 函数根据 Promise 的状态执行相应的回调函数
  executeCallback(callback) {
    const { onResolved, onRejected, resolve, reject } = callback;

    if (this.state === RESOLVED) {
      if (typeof onResolved === 'function') {
        try {
          const result = onResolved(this.value);
          if (result instanceof MyPromise) result.then(resolve).catch(reject)
          else resolve(result); // 将回调函数的返回值作为下一个 Promise 的结果值
        } catch (error) {
          reject(error); // 如果回调函数执行出错,则将 Promise 的状态设置为 REJECTED
        }
      } else {
        resolve(this.value); // 如果没有传入回调函数,则将当前 Promise 的结果值传递给下一个 Promise
      }
    } else if (this.state === REJECTED) {
      if (typeof onRejected === 'function') {
        try {
          const result = onRejected(this.value);
          if (result instanceof MyPromise) result.then(resolve).catch(reject)
          else resolve(result);  // 将回调函数的返回值作为下一个 Promise 的结果值
        } catch (error) {
          reject(error); // 如果回调函数执行出错,则将 Promise 的状态设置为 REJECTED
        }
      } else {
        reject(this.value); // 如果没有传入回调函数,则将当前 Promise 的结果值传递给下一个 Promise
      }
    }
  }
  // then 方法用于注册 Promise 的回调函数,并返回一个新的 Promise 对象
  then(onResolved, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.state === PENDING) {
        // 如果 Promise 的状态为 PENDING,则将回调函数和解决函数存储到 callbacks 数组中
        this.callbacks.push({
          onResolved,
          onRejected,
          resolve,
          reject
        });
      } else {
        // 如果 Promise 的状态已经变为 RESOLVED 或 REJECTED,则将回调函数推到微任务队列中执行
        queueMicrotask(() => {
          this.executeCallback({
            onResolved,
            onRejected,
            resolve,
            reject
          });
        });
      }
    });
  }
  // catch 方法用于注册 Promise 的错误回调函数,并返回一个新的 Promise 对象
  catch(onRejected) {
    return this.then(null, onRejected);
  }
  // 创建一个立即解决的 Promise 对象,并将指定的数据作为解决结果返回。
  static resolve(data) {
    return new MyPromise((resolve) => resolve(data));
  }
  // 创建一个立即拒绝的 Promise 对象,并将指定的原因作为拒绝结果返回。
  static reject(reason) {
    return new MyPromise((_, reject) => reject(reason));
  }
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      const result = [];
      let resolvedCount = 0;
      // 存储每个 Promise 的解决结果

      promises.forEach((p, index) => {
        p
          .then((value) => {
            result[index] = value;
            resolvedCount++;
            // 将解决的 Promise 结果存储到 result 数组中

            resolvedCount === promises.length && resolve(result);
            // 如果所有 Promise 都解决了,则将 result 数组作为解决结果返回
          })
          .catch(reject);
        // 如果有任何一个 Promise 拒绝,则将整个 Promise 设置为拒绝状态
      });
    });
  }
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach((p) => {
        p.then(resolve).catch(reject);
        // 只要有一个 Promise 解决或拒绝,就立即返回对应的结果
      });
    });
  }
  static allSettled(promises) {
    return new MyPromise((resolve) => {
      const results = [];
      let settledCount = 0;
      // 存储每个 Promise 的状态和结果

      const allSettle = () => {
        settledCount++;
        // 统计已经处理完的 Promise 数量

        settledCount === promises.length && resolve(results);
        // 如果所有 Promise 都处理完了,则将 results 数组作为解决结果返回
      };

      promises.forEach((p, index) => {
        p
          .then((value) => {
            results[index] = {
              status: p.state,
              value,
            };
            // 存储解决的 Promise 结果和状态

            allSettle();
          })
          .catch((reason) => {
            results[index] = {
              status: p.state,
              reason,
            };
            // 存储拒绝的 Promise 原因和状态

            allSettle();
          });
      });
    });
  }
  static any(promises) {
    return new MyPromise((resolve, reject) => {
      const reasons = [];
      let rejectedCount = 0;
      // 存储每个 Promise 的拒绝原因

      promises.forEach((p, index) => {
        p
          .then(resolve)
          .catch((reason) => {
            reasons[index] = reason;
            rejectedCount++;
            // 存储拒绝的 Promise 原因

            rejectedCount === promises.length && reject(reasons);
            // 如果所有 Promise 都拒绝了,则将 reasons 数组作为拒绝结果返回
          });
      });
    });
  }
}