手写符合Promise/A+规范的Promise类

一、Promise核心架构设计

1. 三态机制实现原理

javascript 复制代码
static PENDING = "PENDING";
static FULFILLED = "FULFILLED";
static REJECTED = "REJECTED";

status = MyPromise.PENDING;
value = undefined;
handles = [];

状态机设计要点

  • 使用常量定义三种状态,避免魔法字符串
  • 初始状态强制设为PENDING
  • value存储执行结果,实现值传递
  • handles队列存储待执行回调

2. 构造函数核心逻辑

javascript 复制代码
constructor(executor) {
  const resolve = (value) => {
    this.__setState(MyPromise.FULFILLED, value);
  };
  
  const reject = (reason) => {
    this.__setState(MyPromise.REJECTED, reason);
  };

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

执行流程

  1. 创建resolve/reject方法闭包
  2. 立即同步执行executor
  3. 错误捕获机制保障安全

二、异步调度系统解析

1. 微任务调度实现

javascript 复制代码
__async(fn) {
  if (typeof queueMicrotask === "function") {
    queueMicrotask(fn);
  } else if (typeof MutationObserver === "function") {
    // 省略MutationObserver实现
  } else {
    setTimeout(fn);
  }
}

调度策略

  • 优先使用原生微任务API
  • 兼容MutationObserver方案
  • 降级到setTimeout宏任务

2. 回调队列触发机制

javascript 复制代码
__runTask() {
  if (this.status !== MyPromise.PENDING) {
    this.handles.forEach((cb) => this.__async(cb));
    this.handles = [];
  }
}

执行特征

  • 状态变更后触发队列执行
  • 清空队列防止重复执行
  • 异步保证执行顺序

三、链式调用核心实现

1. then方法工作原理

javascript 复制代码
then(onFulfilled, onRejected) {
  return new MyPromise((resolve, reject) => {
    this.handles.push(() => {
      // 处理回调逻辑
    });
    this.__runTask();
  });
}

链式调用流程

  1. 创建新Promise实例
  2. 将处理器加入回调队列
  3. 返回新Promise实现链式

2. 值穿透实现原理

javascript 复制代码
if (typeof cb !== "function") {
  this.status === MyPromise.FULFILLED 
    ? resolve(this.value) 
    : reject(this.value);
  return;
}

特殊处理

  • 非函数参数自动忽略
  • 实现值/异常的冒泡传递
  • 保持与原生Promise一致行为

四、静态方法实现解析

1. 快速创建方法

javascript 复制代码
static resolve(value) {
  if (value instanceof MyPromise) return value;
  return new MyPromise((resolve) => resolve(value));
}

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

功能要点

  • resolve自动解包Promise
  • reject保持原始错误信息
  • 快捷创建已决Promise

2. 并发控制方法

javascript 复制代码
static all(iterable) {
  // 等待所有Promise完成
}

static race(iterable) {
  // 返回最先完成的结果
}

实现差异

方法 完成条件 结果特征 错误处理
all 全部成功 结果数组 快速失败
race 首个完成 单个值 首个异常

五、完整实现代码

javascript 复制代码
class MyPromise {
  // Promise的三种状态常量
  static PENDING = "PENDING";
  static FULFILLED = "FULFILLED";
  static REJECTED = "REJECTED";
  // 设置默认Promise状态为PENDING
  status = MyPromise.PENDING;
  // 设置默认Promise值为undefined
  value = undefined;
  // 定义回调函数
  handles = [];
  constructor(executor) {
    const resolve = (value) => {
      this.__setState(MyPromise.FULFILLED, value);
    };
    const reject = (reason) => {
      this.__setState(MyPromise.REJECTED, reason);
    };
    try {
      // 立即执行传入的函数
      executor(resolve, reject);
    } catch (error) {
      // 如果执行过程中抛出错误,将状态改为REJECTED
      reject(error);
    }
  }

  // 封装then方法
  then(onFulfilled, onRejected) {
    // 返回一个新的Promise实例
    return new MyPromise((resolve, reject) => {
      this.handles.push(() => {
        try {
          // 获取根据状态需要执行的状态函数
          const cb =
            this.status === MyPromise.FULFILLED ? onFulfilled : onRejected;
          // 如果回调不是函数,根据状态直接传递值或抛出错误
          if (typeof cb !== "function") {
            this.status === MyPromise.FULFILLED
              ? resolve(this.value)
              : reject(this.value);
            return;
          }
          // 执行函数获取返回值
          const res = cb(this.value);
          // 如果返回值是一个Promise实例,将其状态和值传递给新的Promise实例
          if (typeof res === "object" && typeof res.then === "function") {
            res.then(resolve, reject);
          } else {
            // 如果返回值不是一个Promise实例,将其值传递给新的Promise实例
            resolve(res);
          }
        } catch (error) {
          reject(error);
        }
      });
      this.__runTask();
    });
  }
  // 封装catch方法
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }
  // 封装finally方法
  finally(onFinally) {
    return this.then(
      (res) => {
        onFinally();
        return res;
      },
      (err) => {
        onFinally();
        throw err;
      }
    );
  }
  // 静态resolve方法
  static resolve(value) {
    if (value instanceof MyPromise) return value;
    return new MyPromise((resolve) => resolve(value));
  }

  // 静态reject方法
  static reject(reason) {
    return new MyPromise((_, reject) => reject(reason));
  }

  // 静态all方法,等待所有Promise完成
  static all(iterable) {
    return new MyPromise((resolve, reject) => {
      const results = [];
      let remaining = iterable.length;
      const checkComplete = () => {
        if (remaining === 0) resolve(results);
      };

      iterable.forEach((item, index) => {
        MyPromise.resolve(item).then((value) => {
          results[index] = value;
          remaining--;
          checkComplete();
        }, reject);
      });
    });
  }

  // 静态race方法,返回最先完成的Promise
  static race(iterable) {
    return new MyPromise((resolve, reject) => {
      for (const item of iterable) {
        MyPromise.resolve(item).then(resolve, reject);
      }
    });
  }
  // 执行微任务数组
  __runTask() {
    // 如果状态不是PENDING,直接返回
    if (this.status !== MyPromise.PENDING) {
      // 在回调执行后立即释放引用
      const temp = this.handles;
      this.handles = [];
      temp.forEach(cb => this.__async(cb));
    }
  }
  // Promise状态更改
  __setState(state, value) {
    // 循环引用检测
    if (value === this) {
      return this.__setState(
        MyPromise.REJECTED,
        new TypeError("Chaining cycle detected")
      );
    }
    // 如果状态不是PENDING,直接返回
    if (this.status !== MyPromise.PENDING) return;
    // 将状态改为REJECTED
    this.status = state;
    // 将值赋值给value
    this.value = value;
    this.__runTask();
  }
  // 定义一个微任务函数
  __async(fn) {
    // 判断是否支持queueMicrotask方法
    if (typeof queueMicrotask === "function") {
      queueMicrotask(fn);
    } else if (typeof MutationObserver === "function") {
      // 如果不支持queueMicrotask方法,使用MutationObserver模拟
      const observer = new MutationObserver(fn);
      const textNode = document.createTextNode(1);
      observer.observe(textNode, {
        characterData: true,
      });
      textNode.data = 2;
    } else {
      // 如果不支持MutationObserver方法,使用setTimeout模拟
      setTimeout(fn);
    }
  }
}

六、应用场景示例

1. 基础链式调用

javascript 复制代码
MyPromise.resolve(1)
  .then(v => v * 2)
  .then(console.log); // 输出2

2. 异常处理流程

javascript 复制代码
new MyPromise((_, reject) => reject("error"))
  .catch(e => console.error(e)) // 输出error
  .finally(() => console.log("cleanup"));

3. 并发控制

javascript 复制代码
const p1 = MyPromise.resolve(1);
const p2 = new MyPromise(r => setTimeout(() => r(2), 100));

MyPromise.all([p1, p2]).then(console.log); // [1,2]
MyPromise.race([p1, p2]).then(console.log); // 1

可通过官方测试套件验证实现完整性:

bash 复制代码
npm install promises-aplus-tests
npx promises-aplus-tests MyPromise.js

七、实现亮点分析

  1. 严格的状态控制

    • 通过setState方法确保状态单向流动
    • 状态变更后立即触发回调执行
  2. 完善的错误处理

    • 自动捕获executor同步错误
    • 链式调用中的错误自动冒泡
    • 提供catch方法集中处理错误
  3. 异步调度优化

    • 优先使用微任务队列
    • 自动降级兼容不同环境
    • 确保回调执行顺序符合规范
  4. 链式调用支持

    • 返回新Promise实现链式调用
    • 自动解包嵌套Promise
    • 支持值穿透特性

本实现完整覆盖Promise核心功能,通过合理的架构设计和边界处理,可作为学习Promise原理的优质参考。实际生产环境建议结合测试用例验证各边界场景。

相关推荐
@大迁世界2 分钟前
TypeScript 的本质并非类型,而是信任
开发语言·前端·javascript·typescript·ecmascript
GIS之路10 分钟前
GDAL 实现矢量裁剪
前端·python·信息可视化
是一个Bug14 分钟前
后端开发者视角的前端开发面试题清单(50道)
前端
Amumu1213816 分钟前
React面向组件编程
开发语言·前端·javascript
持续升级打怪中37 分钟前
Vue3 中虚拟滚动与分页加载的实现原理与实践
前端·性能优化
GIS之路41 分钟前
GDAL 实现矢量合并
前端
hxjhnct43 分钟前
React useContext的缺陷
前端·react.js·前端框架
冰暮流星1 小时前
javascript逻辑运算符
开发语言·javascript·ecmascript
前端 贾公子1 小时前
从入门到实践:前端 Monorepo 工程化实战(4)
前端
菩提小狗1 小时前
Sqlmap双击运行脚本,双击直接打开。
前端·笔记·安全·web安全