登录
首页 >  文章 >  前端

实现符合PromiseA+的MyPromise类详解

时间:2025-10-13 11:19:35 117浏览 收藏

本文旨在深入解析并实现一个符合 Promise A+ 规范的 Promise 类,重点在于其核心机制的理解与应用。Promise A+ 规范要求Promise 具备 pending、fulfilled、rejected 三种状态,且状态一旦改变便不可逆。文章将详细阐述如何通过 resolve 和 reject 函数驱动状态转换,并利用回调队列处理异步操作。同时,着重讲解 then 方法的实现,包括链式调用、异步执行以及对返回值 x 的解析(resolvePromise 函数)。通过本文,你将能够掌握 Promise A+ 的关键点,包括状态管理、异步流程以及 then 方法的处理规则,并能基于此实现一个简化但符合规范的 Promise 类,为深入理解 JavaScript 异步编程打下坚实基础。文章还提供了Promise.resolve、Promise.reject、catch、finally等常用方法的补充实现。

实现一个符合 Promise A+ 规范的 Promise 类,需定义 pending、fulfilled、rejected 三种不可逆状态,通过 resolve 和 reject 函数改变状态并执行对应回调;then 方法返回新 Promise 实现链式调用,根据当前状态异步执行 onFulfilled 或 onRejected,并将结果传入 resolvePromise 处理;resolvePromise 函数递归解析返回值 x,避免循环引用并正确处理 thenable 对象;最后补充 resolve、reject、catch、finally 等常用方法以增强实用性。

如何实现一个符合Promise A+规范的Promise类?

实现一个符合 Promise A+ 规范的 Promise 类,核心在于理解其状态机制、异步解析流程以及 then 方法的处理规则。下面是一个简化但符合规范关键点的实现,帮助你掌握原理。

1. 状态定义与基本结构

Promise 有三种状态:pending(等待)、fulfilled(成功)、rejected(失败)。状态一旦改变,不可逆。

  • 初始化为 pending
  • 只能从 pending → fulfilled 或 pending → rejected
  • 需要存储成功值 value 和失败原因 reason
  • 支持多次调用 then,所以需要维护回调队列
function MyPromise(executor) {
  this.state = 'pending';
  this.value = undefined;
  this.reason = undefined;
  this.onFulfilledCallbacks = [];
  this.onRejectedCallbacks = [];

  const resolve = (value) => {
    if (this.state === 'pending') {
      this.state = 'fulfilled';
      this.value = value;
      this.onFulfilledCallbacks.forEach(fn => fn());
    }
  };

  const reject = (reason) => {
    if (this.state === 'pending') {
      this.state = 'rejected';
      this.reason = reason;
      this.onRejectedCallbacks.forEach(fn => fn());
    }
  };

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

2. 实现 then 方法

then 方法必须返回一个新的 Promise,实现链式调用。这是 Promise A+ 的核心要求之一。

  • 根据当前状态决定执行 onFulfilled 或 onRejected
  • 如果还在 pending,把回调加入队列
  • 返回新 Promise,实现链式调用
MyPromise.prototype.then = function(onFulfilled, onRejected) {
  // 处理穿透,比如 .then().then(value => ...)
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
  onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };

  const promise2 = new MyPromise((resolve, reject) => {
    if (this.state === 'fulfilled') {
      queueMicrotask(() => {
        try {
          const x = onFulfilled(this.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    }

    if (this.state === 'rejected') {
      queueMicrotask(() => {
        try {
          const x = onRejected(this.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    }

    if (this.state === 'pending') {
      this.onFulfilledCallbacks.push(() => {
        queueMicrotask(() => {
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      });

      this.onRejectedCallbacks.push(() => {
        queueMicrotask(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      });
    }
  });

  return promise2;
};

3. 处理返回值 x(resolvePromise)

这个函数是 Promise A+ 规范中最复杂的部分,用于处理 then 回调返回的值 x,决定如何解析新 Promise。

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected'));
  }

  let called = false;

  if (x != null && (typeof x === 'object' || typeof x === 'function')) {
    try {
      const then = x.then;

      if (typeof then === 'function') {
        then.call(
          x,
          y => {
            if (called) return;
            called = true;
            resolvePromise(promise2, y, resolve, reject);
          },
          r => {
            if (called) return;
            called = true;
            reject(r);
          }
        );
      } else {
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    resolve(x);
  }
}

4. 补充常用方法(可选)

虽然不是 A+ 规范强制要求,但可以添加一些静态方法增强实用性。

MyPromise.resolve = function(value) {
  return new MyPromise(resolve => resolve(value));
};

MyPromise.reject = function(reason) {
  return new MyPromise((resolve, reject) => reject(reason));
};

MyPromise.prototype.catch = function(onRejected) {
  return this.then(null, onRejected);
};

MyPromise.prototype.finally = function(callback) {
  return this.then(
    value => MyPromise.resolve(callback()).then(() => value),
    reason => MyPromise.resolve(callback()).then(() => { throw reason; })
  );
};

基本上就这些。这个实现覆盖了 Promise A+ 的主要逻辑:状态管理、异步任务队列、then 链式调用和 resolvePromise 的递归解析。要完全通过官方测试套件(promises-aplus-tests),还需更严格的边界处理,但上述代码已能体现核心思想。

好了,本文到此结束,带大家了解了《实现符合PromiseA+的MyPromise类详解》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>