不多说,先看代码:
export default class CC {
constructor(make) {
this.value = "";
this.state = "pending";
this.success = [];
this.failed = [];
const resolve = (val) => {
if (this.state !== "pending") return;
this.state = "success";
this.value = val;
this.success.forEach(cb => queueMicrotask(cb)); // ✅ 加入微任务队列
this.success = [];
};
const reject = (val) => {
if (this.state !== "pending") return;
this.state = "failed";
this.value = val;
this.failed.forEach(cb => queueMicrotask(cb)); // ✅ 加入微任务队列
this.failed = [];
};
try {
make(resolve, reject);
} catch (err) {
reject(err);
}
}
then(isSuccess, isFailed) {
return new CC((resolve, reject) => { // ✅ 实现链式调用
const successHandler = () => {
try {
resolve(isSuccess?.(this.value)); // ✅ 传递处理结果
} catch (e) {
reject(e);
}
};
const failedHandler = () => {
typeof isFailed === 'function'
? resolve(isFailed(this.value)) // ✅ 捕获错误并继续链式
: reject(this.value); // ✅ 未处理错误时继续抛出
};
if (this.state === "success") {
queueMicrotask(successHandler);
} else if (this.state === "failed") {
queueMicrotask(failedHandler);
} else {
this.success.push(successHandler);
this.failed.push(failedHandler);
}
});
}
}
// 测试用例 ✅
new CC((_, reject) => {
setTimeout(() => reject(33333), 3000)
}).then(
val => console.log('Success:', val),
err => console.log('Caught Error:', err) // 3秒后输出 ▶ Caught Error: 33333
);
一、构造函数解析
constructor(make) {
this.value = ""; // 存储终值/拒因
this.state = "pending"; // 状态机:pending/success/failed
this.success = []; // 成功回调队列
this.failed = []; // 失败回调队列
// 核心状态转换函数
const resolve = (val) => {
if (this.state !== "pending") return;
this.state = "success";
this.value = val;
this.success.forEach(cb => queueMicrotask(cb)); // ✅ 微任务调度
this.success = []; // 清空队列避免重复执行
};
const reject = (val) => { /* 类似 resolve 逻辑 */ };
try {
make(resolve, reject); // 同步执行执行器函数
} catch (err) {
reject(err); // ✅ 同步错误直接触发拒绝
}
}
关键特性:
- 状态不可逆:通过
state变量确保只能从pending转换到终态 - 微任务队列:使用
queueMicrotask实现符合规范的异步调度 - 错误边界:
try/catch包裹执行器函数,同步错误自动触发reject
二、链式 then 方法实现
then(isSuccess, isFailed) {
return new CC((resolve, reject) => { // ✅ 返回新实例实现链式
const successHandler = () => {
try {
// ✅ 透传处理结果或捕获异常
resolve(isSuccess?.(this.value));
} catch (e) {
reject(e);
}
};
const failedHandler = () => {
if (typeof isFailed === 'function') {
resolve(isFailed(this.value)); // ✅ 错误被处理后继续链式
} else {
reject(this.value); // ✅ 未处理错误继续向下传递
}
};
// 根据当前状态调度处理程序
if (this.state === "success") {
queueMicrotask(successHandler);
} else if (this.state === "failed") {
queueMicrotask(failedHandler);
} else {
this.success.push(successHandler); // 订阅状态变更
this.failed.push(failedHandler);
}
});
}
核心机制:
-
返回新 Promise:每个
then生成独立的新实例,形成调用链 -
值穿透规则:
- 成功回调 (
isSuccess) 不存在时透传终值 - 失败回调 (
isFailed) 不存在时透传拒因
- 成功回调 (
-
错误冒泡:
- 回调中的同步错误会被捕获并触发新实例的
reject - 处理过的错误通过
resolve转换为成功状态
- 回调中的同步错误会被捕获并触发新实例的
为什么在then中使用 return 一个新的实例返回一个promise?
是为了能够进行多级的链式调用,比如 new promise(x).then(x).then(x),then本身就是返回一个promise对象