实现 Promise
本文内容基于 AI 生成结果整理,可能包含不准确信息,仅供参考使用。
跟着 AI 学习手搓一个 Promise 类
v1.0 最基础版本
状态管理 + 同步 then
js
class MyPromise {
constructor(executor) {
this.state = "pending"; // 三种状态: pending, fulfilled, rejected
this.value = undefined; // 成功的结果
this.reason = undefined; // 失败的原因
const resolve = (value) => {
if (this.state == "pending") {
this.state = "fulfilled";
this.value = value;
}
};
const reject = (reason) => {
if (this.state == "pending") {
this.state = "rejected";
this.reason = reason;
}
};
// 立即执行
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 基础 then 方法,只处理同步
then(onFulfilled, onRejected) {
if (this.state == "fulfilled") {
onFulfilled(this.value);
}
if (this.state == "rejected") {
onRejected(this.reason);
}
}
}
// 测试 v1.0
console.log("v1.0 测试");
const p1 = new MyPromise((resolve) => {
resolve("success!");
});
p1.then((value) => console.log(value));v2.0 支持异步操作
js
class MyPromise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
// 新增:回调队列
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 (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
if (this.state == "fulfilled") {
onFulfilled(this.value);
}
if (this.state == "rejected") {
onRejected(this.reason);
}
if (this.state == "pending") {
// 将回调存入队列
this.onFulfilledCallbacks.push(() => onFulfilled(this.value));
this.onRejectedCallbacks.push(() => onRejected(this.reason));
}
}
}
// 测试 v2.0
console.log("v2.0 测试");
const p2 = new MyPromise((resolve) => {
setTimeout(() => {
resolve("sync success!");
}, 1000);
});
p2.then((value) => console.log(value));v3.0 实现链式调用
js
class MyPromise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
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 (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
// 处理值穿透:如果不是函数,就创建默认函数
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
// 返回新的 Promise
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === "fulfilled") {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === "rejected") {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === "pending") {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise2;
}
}
// 测试 v3.0
console.log("v3.0 测试");
const p3 = new MyPromise((resolve) => {
resolve(1);
});
p3.then((value) => {
console.log("第一次:", value); // 1
return value + 1;
})
.then((value) => {
console.log("第二次:", value); // 2
return new MyPromise((resolve) => resolve(value + 1));
})
.then((value) => {
console.log("第三次:", value); // 3
});setTimeout 0 的关键作用
- 确保异步执行
- 处理链式调用的时机
v4.0 处理 Promise 返回值
js
class MyPromise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
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 (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
const promise2 = new MyPromise((resolve, reject) => {
const handleCallback = (callback, valueOrReason) => {
setTimeout(() => {
try {
const x = callback(valueOrReason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
};
if (this.state === "fulfilled") {
handleCallback(onFulfilled, this.value);
} else if (this.state === "rejected") {
handleCallback(onRejected, this.reason);
} else if (this.state === "pending") {
this.onFulfilledCallbacks.push(() =>
handleCallback(onFulfilled, this.value)
);
this.onRejectedCallbacks.push(() =>
handleCallback(onRejected, this.reason)
);
}
});
return promise2;
}
// 添加 catch 方法
catch(onRejected) {
return this.then(null, onRejected);
}
}
// Promise 解析函数
function resolvePromise(promise2, x, resolve, reject) {
// 防止循环引用
if (promise2 === x) {
return reject(new TypeError("循环引用"));
}
// 如果 x 是 promise
if (x instanceof MyPromise) {
x.then((y) => resolvePromise(promise2, y, resolve, reject), reject);
}
// 如果 x 是对象或函数
else if (x !== null && (typeof x === "object" || typeof x === "function")) {
let then;
try {
then = x.then;
} catch (error) {
return reject(error);
}
if (typeof then === "function") {
let called = false;
try {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} catch (error) {
if (!called) {
reject(error);
}
}
} else {
resolve(x);
}
}
// 基本类型直接 resolve
else {
resolve(x);
}
}
// 测试 v4.0
console.log("v4.0 测试");
const p4 = new MyPromise((resolve) => resolve(1));
p4.then((value) => {
console.log("值:", value);
return new MyPromise((resolve) => resolve(value + 1));
})
.then((value) => {
console.log("新 Promise 返回值:", value);
return { data: value + 1 };
})
.then((value) => {
console.log("对象返回值:", value);
});v5.0 添加静态方法
js
class MyPromise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
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 (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
const promise2 = new MyPromise((resolve, reject) => {
const handleCallback = (callback, valueOrReason) => {
setTimeout(() => {
try {
const x = callback(valueOrReason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
};
if (this.state === "fulfilled") {
handleCallback(onFulfilled, this.value);
} else if (this.state === "rejected") {
handleCallback(onRejected, this.reason);
} else if (this.state === "pending") {
this.onFulfilledCallbacks.push(() =>
handleCallback(onFulfilled, this.value)
);
this.onRejectedCallbacks.push(() =>
handleCallback(onRejected, this.reason)
);
}
});
return promise2;
}
catch(onRejected) {
return this.then(null, onRejected);
}
static resolve(value) {
if (value instanceof MyPromise) {
return value;
}
if (value && typeof value.then === "function") {
return new MyPromise(value.then);
}
return new MyPromise((resolve) => resolve(value));
}
static reject(reason) {
return new MyPromise((_, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let completed = 0;
if (promises.length === 0) {
resolve(results);
return;
}
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then((value) => {
results[index] = value;
completed++;
if (completed === promises.length) {
resolve(results);
}
}, reject);
});
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((promise) => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
static allSettled(promises) {
return new MyPromise((resolve) => {
const results = [];
let completed = 0;
const processResult = (index, status, valueOrReason) => {
results[index] =
status === "fulfilled"
? { status: "fulfilled", value: valueOrReason }
: { status: "rejected", reason: valueOrReason };
completed++;
if (completed === promises.length) {
resolve(results);
}
};
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
(value) => processResult(index, "fulfilled", value),
(reason) => processResult(index, "rejected", reason)
);
});
});
}
finally(callback) {
return this.then(
(value) => MyPromise.resolve(callback()).then(() => value),
(reason) =>
MyPromise.resolve(callback()).then(() => {
throw reason;
})
);
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError("循环引用"));
}
if (x instanceof MyPromise) {
x.then((y) => resolvePromise(promise2, y, resolve, reject), reject);
} else if (x !== null && (typeof x === "object" || typeof x === "function")) {
let then;
try {
then = x.then;
} catch (error) {
return reject(error);
}
if (typeof then === "function") {
let called = false;
try {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} catch (error) {
if (!called) {
reject(error);
}
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}
// 测试 v5.0
console.log("v5.0 测试");
// 测试 MyPromise.all
MyPromise.all([
MyPromise.resolve(1),
MyPromise.resolve(2),
new MyPromise((resolve) => setTimeout(() => resolve(3), 100)),
]).then((values) => {
console.log("all 结果:", values); // [1, 2, 3]
});
// 测试 MyPromise.race
MyPromise.race([
new MyPromise((resolve) => setTimeout(() => resolve("快的"), 50)),
new MyPromise((resolve) => setTimeout(() => resolve("慢的"), 100)),
]).then((value) => {
console.log("race 结果:", value); // "快的"
});
// 测试 MyPromise.resolve/reject
MyPromise.resolve("直接成功").then(console.log);
MyPromise.reject("直接失败").catch(console.error);最终完整版本
js
class MyPromise {
static PENDING = "pending";
static FULFILLED = "fulfilled";
static REJECTED = "rejected";
constructor(executor) {
this.state = MyPromise.PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state !== MyPromise.PENDING) return;
// 处理 thenable 对象
if (value && typeof value.then === "function") {
value.then(resolve, reject);
return;
}
this.state = MyPromise.FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach((fn) => fn());
};
const reject = (reason) => {
if (this.state !== MyPromise.PENDING) return;
this.state = MyPromise.REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) => v;
onRejected =
typeof onRejected === "function"
? onRejected
: (e) => {
throw e;
};
const promise2 = new MyPromise((resolve, reject) => {
const handleFulfilled = () => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
};
const handleRejected = () => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
};
if (this.state === MyPromise.FULFILLED) {
handleFulfilled();
} else if (this.state === MyPromise.REJECTED) {
handleRejected();
} else {
this.onFulfilledCallbacks.push(handleFulfilled);
this.onRejectedCallbacks.push(handleRejected);
}
});
return promise2;
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(callback) {
return this.then(
(value) => MyPromise.resolve(callback()).then(() => value),
(reason) =>
MyPromise.resolve(callback()).then(() => {
throw reason;
})
);
}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise((resolve) => resolve(value));
}
static reject(reason) {
return new MyPromise((_, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let count = 0;
const processResult = (index, value) => {
results[index] = value;
if (++count === promises.length) {
resolve(results);
}
};
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
(value) => processResult(index, value),
reject
);
});
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((promise) => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
static allSettled(promises) {
return new MyPromise((resolve) => {
const results = [];
let count = 0;
const processResult = (index, status, valueOrReason) => {
results[index] =
status === "fulfilled"
? { status: "fulfilled", value: valueOrReason }
: { status: "rejected", reason: valueOrReason };
if (++count === promises.length) {
resolve(results);
}
};
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
(value) => processResult(index, "fulfilled", value),
(reason) => processResult(index, "rejected", reason)
);
});
});
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError("循环引用"));
}
if (x instanceof MyPromise) {
x.then((y) => resolvePromise(promise2, y, resolve, reject), reject);
} else if (x && (typeof x === "object" || typeof x === "function")) {
let then;
try {
then = x.then;
} catch (error) {
return reject(error);
}
if (typeof then === "function") {
let called = false;
try {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} catch (error) {
if (!called) reject(error);
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}