1 回答
TA贡献1796条经验 获得超4个赞
当调用时,CustomPromise.then
您可以看到您只是在继续input
并立即调用它,而不管承诺的状态如何。我认为您想要做的是创建一个task queue
,并在解决后,您将继续执行它。
您还错过了一些关键的事情。
首先,您需要维护一个
state
内部的 Promise,以便您知道 Promise 何时发生settled
。这使得您无法多次解决/拒绝承诺。您的
reject
函数可能不应该只是执行输入。您通常将 a 传递reason
给拒绝,然后它将执行所有catch
任务。没有链接支持。不确定这是否是你的目标。
const functionOrNoop = (fn) => {
let result = () => {};
if (typeof fn === "function") {
result = fn;
}
return result;
};
class CustomPromise {
constructor(executor) {
this.queue = [];
this.state = "pending";
this.value = null;
this.reason = null;
executor(this.onResolve, this.onReject);
}
static reject(reason) {
return new CustomPromise((_, reject) => reject(reason));
}
static resolve(value) {
return new CustomPromise((resolve) => resolve(value));
}
then(fn) {
return new CustomPromise((resolve, reject) => {
const resolved = (value) => {
try {
resolve(fn(value))
} catch (e) {
reject(e);
}
};
this.enqueue({
resolved,
rejected: reject
});
});
}
catch (fn) {
return new CustomPromise((resolve, reject) => {
const rejected = (reason) => {
try {
resolve(fn(reason))
} catch (e) {
reject(e);
}
};
this.enqueue({
rejected
});
});
}
onResolve = (value) => {
if (this.state === "pending") {
this.state = "resolved";
this.value = value;
this.finalize();
}
}
onReject = (reason) => {
if (this.state === "pending") {
this.state = "rejected";
this.reason = reason;
this.finalize();
}
};
enqueue(task) {
if (this.state === "pending") {
this.queue.push(task);
} else {
this.eval(task);
}
}
eval(task) {
if (this.state === "resolved") {
functionOrNoop(task.resolved)(this.value);
} else if (this.state === "rejected") {
functionOrNoop(task.rejected)(this.reason);
}
}
finalize() {
this.queue.forEach((task) => this.eval(task));
this.queue = [];
}
}
const p = CustomPromise.resolve("hello")
p
.then((value) => value.toUpperCase())
.then((value) => `J${value.slice(1)}`)
.then((value) => console.log(value))
p.then((value) => console.log(value));
p
.then(() => {
throw new Error(":(")
})
.catch((e) => console.log(e.message))
.then(() => {
throw new Error(":)")
})
.then(() => console.log("SHOULD NOT CALL!"))
.catch((e) => console.log(e.message));
这是一个示例(所以预计会有错误),但它封装了我上面提到的一些内容。Promise 确实很复杂,您会错过诸如“微任务”之类的东西以及数万小时的测试、开发和审查。
添加回答
举报