第 27 题:Promise 实现原理(含手写 Promise)

好的,进入 第 32 题:Promise 实现原理(含手写 Promise)

这是 前端顶级高频题,高级前端/资深前端必问。


第 32 题:Promise 的原理是什么?如何手写一个 Promise?(详细版)


一、Promise 的本质是什么?(核心一句话)

Promise 是一个状态机 + 订阅发布模式的异步任务容器。

它有三个状态:

  • pending
  • fulfilled
  • rejected

状态只能:

✔ 从 pending → fulfilled

✔ 从 pending → rejected

✖ 不能从 fulfilled/rejected 回到 pending


二、Promise 做了什么?(面试官要的)

  1. 把异步操作包装成一个对象
  2. 可以通过 then / catch 注册回调
  3. 状态变化后一旦确定,不可逆
  4. 所有 then 回调都是微任务(microtask)
  5. 链式调用支持,返回新的 Promise

三、Promise 的关键实现点(面试必考 5 点)

  1. 状态管理(state)

  2. 成功值 & 失败原因(value,reason)

  3. 回调依赖队列(onFulfilledQueue / onRejectedQueue)

  4. 状态变更后触发回调(发布-订阅)

  5. then 的链式调用要返回新 Promise,处理三种情况:

    • 返回普通值 → resolve
    • 返回 Promise → 等待这个 Promise
    • 抛错 → reject

四、最常见面试要求:手写一个最小 Promise

下面是一个 真正能运行 的、最简版 Promise 实现

面试考这个版本最稳。


五、手写 Promise(简化可运行版)

ini 复制代码
class MyPromise {
  constructor(executor) {
    this.state = 'pending';
    this.value = null;
    this.reason = null;

    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onFulfilledCallbacks.forEach(fn => fn());
      }
    };

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };

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

  then(onFulfilled, onRejected) {
    // 如果用户没传,就兜底
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v;
    onRejected = typeof onRejected === 'function' ? onRejected : (e) => { throw e; };

    return new MyPromise((resolve, reject) => {
      if (this.state === 'fulfilled') {
        queueMicrotask(() => {
          try {
            const x = onFulfilled(this.value);
            resolve(x);
          } catch (err) {
            reject(err);
          }
        });
      }

      if (this.state === 'rejected') {
        queueMicrotask(() => {
          try {
            const x = onRejected(this.reason);
            resolve(x);
          } catch (err) {
            reject(err);
          }
        });
      }

      if (this.state === 'pending') {
        this.onFulfilledCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              const x = onFulfilled(this.value);
              resolve(x);
            } catch (err) {
              reject(err);
            }
          });
        });

        this.onRejectedCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              const x = onRejected(this.reason);
              resolve(x);
            } catch (err) {
              reject(err);
            }
          });
        });
      }
    });
  }
}

六、这个 Promise 实现能做什么?

✔ then 链式调用

✔ 异步执行

✔ 回调队列

✔ 状态不可逆

✔ 微任务执行模型

✔ 抛错捕获

基本等同于简化版 ES Promise,面试够用。


七、面试官会继续追问什么?(提前准备)

我给你梳理好了:

1. 如何实现 catch

kotlin 复制代码
catch(errFn) {
  return this.then(null, errFn);
}

2. 如何实现 finally

javascript 复制代码
finally(fn) {
  return this.then(
    v => Promise.resolve(fn()).then(() => v),
    e => Promise.resolve(fn()).then(() => { throw e; })
  );
}

3. 如何处理 then 返回 Promise 本身?

需要 resolvePromise 解析器(完整版才有)

4. then 为什么是微任务?

因为 ES 标准规定:

Promise reaction 必须在当前执行栈结束后、微任务队列中执行。


八、20 秒背诵版(面试必杀)

Promise 是一个状态机(pending → fulfilled/rejected),并使用发布订阅模式来管理回调。then 的回调会被加入微任务队列,状态变更后触发执行。链式调用通过返回新的 Promise 并解析返回结果实现。如果返回值是普通值直接 resolve,如果返回的是 Promise,就等待它完成。


是否进入 第 33 题:async/await 原理(为什么 await 是 Promise 的语法糖)

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