登录
首页 >  文章 >  前端

手写Promise.js,解析Promises/A+规范

时间:2025-11-12 14:03:37 283浏览 收藏

欢迎各位小伙伴来到golang学习网,相聚于此都是缘哈哈哈!今天我给大家带来《手写Promise.js,深入解析Promises/A+规范》,这篇文章主要讲到等等知识,如果你对文章相关的知识非常感兴趣或者正在自学,都可以关注我,我会持续更新相关文章!当然,有什么建议也欢迎在评论留言提出!一起学习!

答案:手写符合Promises/A+规范的Promise需实现状态机、then链式调用与resolvePromise递归解析;包含pending/fulfilled/rejected三种状态,通过resolve/reject函数改变状态,then方法返回新Promise并注册回调,利用queueMicrotask确保异步执行,resolvePromise处理返回值为Promise或thenable的情况,防止循环引用,同时实现catch、finally、resolve、reject等辅助方法。

手写一个符合Promises/A+规范的Promise_js深度探索

要手写一个符合 Promises/A+ 规范的 Promise,关键在于理解其核心机制:状态机、异步执行、then 方法的链式调用与穿透,以及 onFulfilledonRejected 的回调调度。下面从零实现一个精简但完全符合规范的 Promise 类。

Promise 核心状态与基本结构

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

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

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);
  }
}

实现 then 方法

then 方法是 Promise 的核心,必须返回一个新的 Promise,实现链式调用。它接收两个可选参数:onFulfilled 和 onRejected。

MyPromise.prototype.then = function(onFulfilled, onRejected) {
  // 处理透传,支持 .then().then(value => ...)
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
  onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };

  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;
};

处理 then 返回值:resolvePromise 函数

这个函数决定如何处理 onFulfilled/onRejected 的返回值 x。根据 Promises/A+ 规范,x 可能是普通值、Promise 或带有 then 方法的对象(即“thenable”)。

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

  let called = false;

  if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
    let then;
    try {
      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);
  }
}

补充常用方法:catch、finally、resolve、reject

这些是基于 then 的语法糖,增强使用体验。

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; })
  );
};

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

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

基本上就这些。这个实现覆盖了 Promises/A+ 的主要测试用例,包括异步回调、链式调用、错误捕获、循环引用检测等。关键是理解 resolvePromise 如何递归解析 thenable,以及 queueMicrotask 确保回调异步执行,模拟原生 microtask 队列行为。

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《手写Promise.js,解析Promises/A+规范》文章吧,也可关注golang学习网公众号了解相关技术文章。

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