手写符合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原理的优质参考。实际生产环境建议结合测试用例验证各边界场景。

相关推荐
Bl_a_ck几秒前
【React】Craco 简介
开发语言·前端·react.js·typescript·前端框架
为美好的生活献上中指27 分钟前
java每日精进 5.11【WebSocket】
java·javascript·css·网络·sql·websocket·网络协议
augenstern4161 小时前
webpack重构优化
前端·webpack·重构
海拥✘1 小时前
CodeBuddy终极测评:中国版Cursor的开发革命(含安装指南+HTML游戏实战)
前端·游戏·html
寧笙(Lycode)2 小时前
React系列——HOC高阶组件的封装与使用
前端·react.js·前端框架
asqq82 小时前
CSS 中的 ::before 和 ::after 伪元素
前端·css
拖孩2 小时前
【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
前端·javascript·css·vue.js·ui组件库
苹果电脑的鑫鑫2 小时前
element中表格文字剧中可以使用的属性
javascript·vue.js·elementui
Hejjon2 小时前
Vue2 elementUI 二次封装命令式表单弹框组件
前端·vue.js
一丝晨光3 小时前
数值溢出保护?数值溢出应该是多少?Swift如何让整数计算溢出不抛出异常?类型最大值和最小值?
java·javascript·c++·rust·go·c·swift