手写Promise--教学版本

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

目标:

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

一、Promise 的核心概念

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

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

状态特性

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

  2. pending → fulfilledpending → 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 原理复盘
  • 手写代码能力展示
相关推荐
kyriewen10 小时前
Anthropic 估值逼近万亿美元,Claude Sonnet 5 + Claude Science 一天两连发
前端·ai编程·claude
小徐_233311 小时前
Wot UI 2.2.0 发布:Button 新增 subtle,VideoPreview 预览体验继续增强
前端·微信小程序·uni-app
山河木马12 小时前
矩阵专题3-怎么创建投影矩阵(uProjectionMatrix)
javascript·webgl·计算机图形学
天蓝色的鱼鱼13 小时前
关于 CSS 你可能不知道的属性,但关键时刻很有用
前端·css
泯泷14 小时前
第 2 篇:设计第一套字节码:Opcode、Instruction 与 Constant Pool
前端·javascript·安全
妙码生花14 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
泯泷14 小时前
第 1 篇:从 1 + 2 开始:亲手写出第一台 JSVM
前端·javascript·安全
团团崽_七分甜14 小时前
Spring Boot 核心知识点总结
前端
lichenyang45314 小时前
从一个按钮开始,理解 ASCF 框架到底在做什么
前端