好的,进入 第 32 题:Promise 实现原理(含手写 Promise) 。
这是 前端顶级高频题,高级前端/资深前端必问。
第 32 题:Promise 的原理是什么?如何手写一个 Promise?(详细版)
一、Promise 的本质是什么?(核心一句话)
Promise 是一个状态机 + 订阅发布模式的异步任务容器。
它有三个状态:
- pending
- fulfilled
- rejected
状态只能:
✔ 从 pending → fulfilled
✔ 从 pending → rejected
✖ 不能从 fulfilled/rejected 回到 pending
二、Promise 做了什么?(面试官要的)
- 把异步操作包装成一个对象
- 可以通过 then / catch 注册回调
- 状态变化后一旦确定,不可逆
- 所有 then 回调都是微任务(microtask)
- 链式调用支持,返回新的 Promise
三、Promise 的关键实现点(面试必考 5 点)
-
状态管理(state)
-
成功值 & 失败原因(value,reason)
-
回调依赖队列(onFulfilledQueue / onRejectedQueue)
-
状态变更后触发回调(发布-订阅)
-
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 的语法糖) ?