手写Promise最终版本

手写 Promise 全实现

目标:完整实现一个符合 Promise/A+ 行为模型的 Promise ,覆盖 then 链式调用、值穿透、异常捕获、Promise.resolve / reject / all / race`,并严格使用 微任务(queueMicrotask) 。


一、整体设计思路

Promise 的三大核心要素

  1. 状态管理

    • pending
    • fulfilled
    • rejected
  2. 结果存储

    • 成功值 / 失败原因只能设置一次
  3. 回调队列

    • pending 状态下,then 注册的回调需要被缓存
    • 状态确定后统一执行

二、Promise 构造函数实现

kotlin 复制代码
function Promise(executor) {
  this.PromiseState = "pending"
  this.PromiseResult = null
  this.callBacks = []

  const self = this

  function resolve(data) {
    if (self.PromiseState !== "pending") return

    // 处理 resolve(Promise)
    if (data instanceof Promise) {
      data.then(resolve, reject)
      return
    }

    self.PromiseState = "fulfilled"
    self.PromiseResult = data

    self.callBacks.forEach(cb => {
      if (cb.onResolve) {
        queueMicrotask(() => cb.onResolve(data))
      }
    })
  }

  function reject(data) {
    if (self.PromiseState !== "pending") return

    // 处理 reject(Promise)
    if (data instanceof Promise) {
      data.then(resolve, reject)
      return
    }

    self.PromiseState = "rejected"
    self.PromiseResult = data

    self.callBacks.forEach(cb => {
      if (cb.onReject) {
        queueMicrotask(() => cb.onReject(data))
      }
    })
  }

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

关键点解析

  • 状态只能从 pending → fulfilled / rejected
  • resolve / reject 内部必须防止重复执行
  • executor 同步异常需要被 reject 捕获
  • 所有 then 回调必须异步执行(微任务)

三、then 方法实现(核心)

javascript 复制代码
Promise.prototype.then = function (onResolve, onReject) {
  const self = this

  // 值穿透 & 异常穿透
  if (typeof onResolve !== "function") {
    onResolve = result => result
  }
  if (typeof onReject !== "function") {
    onReject = reason => { throw reason }
  }

  return new Promise((resolve, reject) => {
    function callFunction(fn) {
      try {
        const result = fn(self.PromiseResult)
        if (result instanceof Promise) {
          result.then(resolve, reject)
        } else {
          resolve(result)
        }
      } catch (error) {
        reject(error)
      }
    }

    if (self.PromiseState === "fulfilled") {
      queueMicrotask(() => callFunction(onResolve))
    }

    if (self.PromiseState === "rejected") {
      queueMicrotask(() => callFunction(onReject))
    }

    if (self.PromiseState === "pending") {
      self.callBacks.push({
        onResolve: () => callFunction(onResolve),
        onReject: () => callFunction(onReject)
      })
    }
  })
}

then 的核心规则

  1. then 必须返回一个新的 Promise

  2. 回调返回值:

    • 普通值 → resolve
    • Promise → 状态跟随
    • throw → reject
  3. 支持链式调用 & 错误冒泡


四、Promise.resolve / Promise.reject

javascript 复制代码
Promise.resolve = function (data) {
  return new Promise((resolve, reject) => {
    if (data instanceof Promise) {
      data.then(resolve, reject)
    } else {
      resolve(data)
    }
  })
}

Promise.reject = function (data) {
  return new Promise((resolve, reject) => {
    reject(data)
  })
}

五、Promise.race 实现

javascript 复制代码
Promise.race = function (promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(resolve, reject)
    }
  })
}

行为特点

  • 谁先改变状态,用谁的结果
  • 不关心其它 Promise 状态

六、Promise.all 实现

ini 复制代码
Promise.all = function (promises) {
  let count = 0
  const result = []

  return new Promise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(value => {
        result[i] = value
        count++
        if (count === promises.length) {
          resolve(result)
        }
      }, reject)
    }
  })
}

行为特点

  • 顺序与输入一致
  • 任何一个 reject,整体 reject

七、完整能力覆盖检查表

  • 状态不可逆
  • executor 异常捕获
  • then 链式调用
  • 值穿透 / 错误穿透
  • 微任务调度
  • Promise.resolve / reject
  • Promise.all / race

八、总结

这版 Promise:

  • 是面试可手写级别
  • 是 Promise/A+ 思维完整实现
  • 已具备真实 Promise 的 90% 行为特征

📌 一句话总结:

真正理解 Promise,不是会用,而是能写出来。

相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万4 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋4 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
晨米酱4 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
卡布鲁4 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄4 天前
JavaScript 隐式全局变量解析
javascript
彧azz4 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
汉堡大王95274 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端