手写Promise--教学版本

手写 Promise 实现与原理(面试向)

目标:

  • 理解 Promise 的状态机模型
  • 掌握 then 链式调用的本质
  • 能在面试中手写 + 讲清楚 Promise 核心机制

一、Promise 的核心概念

Promise 本质是一个 状态机,只存在三种状态:

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)

状态特性

  1. 状态一旦改变,不可逆

  2. pending → fulfilled 或 pending → rejected

  3. Promise 内部维护:

    • 当前状态 PromiseState
    • 当前结果 PromiseResult
    • 回调队列 callBacks

二、Promise 构造函数实现

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

  const self = this

  function resolve(data) {
    if (self.PromiseState !== "pending") return
    self.PromiseState = "fulfilled"
    self.PromiseResult = data
    self.callBacks.forEach(cb => cb.onResolve && cb.onResolve(data))
  }

  function reject(reason) {
    if (self.PromiseState !== "pending") return
    self.PromiseState = "rejected"
    self.PromiseResult = reason
    self.callBacks.forEach(cb => cb.onReject && cb.onReject(reason))
  }

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

设计要点

  • 使用 self = this 确保 this 指向稳定
  • executor 执行包裹在 try / catch 中,异常直接 reject
  • resolve / reject 中做 状态保护,防止多次调用
  • 这里你也可以用箭头函数的特性实现,不过用self更好理解

三、then 方法的核心思想

then 的本质:返回一个新的 Promise

then 的三大职责

  1. 处理 fulfilled / rejected 状态
  2. 支持 then 链式调用
  3. 支持异常向后传递

四、then 的默认行为(非常重要)

javascript 复制代码
if (typeof onResolve !== 'function') {
  onResolve = value => value
}

if (typeof onReject !== 'function') {
  onReject = reason => { throw reason }
}

为什么要这样?

  • 保证 值穿透:

    javascript 复制代码
    Promise.resolve(1).then().then(v => console.log(v)) // 1
  • 保证 错误冒泡:

    javascript 复制代码
    Promise.reject('err').then().then(null, e => console.log(e))

五、then 的完整实现

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

  if (typeof onResolve !== "function") onResolve = v => v
  if (typeof onReject !== "function") onReject = r => { throw r }

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

    if (self.PromiseState === "fulfilled") {
      handle(onResolve)
    }

    if (self.PromiseState === "rejected") {
      handle(onReject)
    }

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

六、Promise 链式调用原理

javascript 复制代码
new Promise(r => r(1))
  .then(v => v + 1)
  .then(v => new Promise(r => r(v + 1)))
  .then(console.log) // 3

原理总结

  • then 必须返回新 Promise
  • 上一个 then 的返回值,决定下一个 then 的状态
  • 返回普通值 → fulfilled
  • 返回 Promise → 状态由该 Promise 决定
  • 抛异常 → rejected

七、Promise.resolve / Promise.reject 实现

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

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

八、当前实现的不足(面试加分点)

1️ then 回调是同步的

  • 原生 Promise 的 then 回调是 微任务
  • 可用 queueMicrotask / setTimeout 模拟

2️ 使用了 instanceof Promise

  • 规范中使用 thenable 解析
  • { then(resolve) { resolve(1) } } 也应被视为 Promise

九、面试总结一句话

Promise 的核心是状态机模型,then 返回新 Promise,

通过默认回调实现值穿透和错误冒泡,

真正规范实现中 then 回调会被放入微任务队列执行。


十、阶段总结

已掌握:

  • Promise 状态流转
  • then 链式调用本质
  • 错误捕获与传递

下一步:

  • Promise/A+ 规范(resolvePromise)
  • 微任务调度实现

本笔记适用于:

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