Hi, 👋 ! 如果您发现有什么错误的地方,点这里可以提 issue,🤝🤝
by poplark
new Promise((resolve, reject) {
// ...
// if xxx resolve(xxx)
// if yyy reject(yyy)
}).then((data) => {
// ...
}, (err) => {
// ...
});
new Promise((resolve, reject) {
// ...
// if xxx resolve(xxx)
// if yyy reject(yyy)
}).then((data) => {
// ...
}).catch((err) => {
// ...
});
一个 Promise 对象内部只会有三种状态: pending, fulfilled, rejected,初始状态永远为 pending,而且一旦转变成 fulfilled 或 rejected 状态,则永远定格为该状态。
当转变为 fulfilled 状态之后,内部会记录 fulfilled 时对应的 data 用于传给 then 中的 onFulfilled 回调函数。 当转变为 rejected 状态之后,内部会记录 rejected 时对应的 reason 用于传给 then 或 catch 中的 onRejected 回调函数。
特别地,由于 Promise 支持链式调用,所以像 then, catch 的返回值都为一个 Promise 对象。
// 1. 定义内部状态
enum MPromiseState {
pending = 0,
fulfilled = 1,
rejected = 2,
}
interface ResolveFunc<T> {
(data: T): any;
}
interface RejectFunc {
(reason: any): any;
}
interface Handler<T> {
(resolve?: ResolveFunc<T>, reject?: RejectFunc): any;
}
type onFulfilledFunc<T> = ResolveFunc<T>;
type onRejectedFunc = RejectFunc;
class MPromise<T> {
private state = MPromiseState.pending;
private data: T;
private reason: any;
// 12. fulfilled 时执行的回调函数,可由下级 Promise 注册,进而通知到下级 Promise
private onFulfilled: onFulfilledFunc<T>;
// 13. rejected 时执行的回调函数,可由下级 Promise 注册,进而通知到下级 Promise
private onRejected: onRejectedFunc;
constructor(handler: Handler<T>) {
// todo - verify handler function
// 2. 处理 Handler 函数
// 3. 定义 resolve 和 reject 函数,作为 handler 函数的参数,由程序在 handler 中调用,以改变 Promise 的内部状态,进而唤醒 then 或 catch 中传入的 onFulfilled 或 onRejected 回调函数;
const resolve: ResolveFunc<T> = (data) => {
if (this.state !== MPromiseState.pending) {
return; // 当 Promise 的状态已变为非 pending 时,则不再处理状态的变更
}
this.state = MPromiseState.fulfilled;
this.data = data;
// 14. 执行 onFulfilled
this.onFulfilled && this.onFulfilled(this.data);
}
const reject: RejectFunc = (reason) => {
if (this.state !== MPromiseState.pending) {
return; // 当 Promise 的状态已变为非 pending 时,则不再处理状态的变更
}
this.state = MPromiseState.rejected;
this.reason = reason;
// 15. 执行 onFulfilled
this.onRejected && this.onRejected(this.reason);
}
// 16. 制造延迟执行函数,确保将 onFulfilled 和 onRejected 函数插入到任务队列尾部
const delay = (fn: Function): Function => {
return function (...args) {
setTimeout(() => {
fn(...args);
}, 0);
}
}
try {
handler(delay(resolve) as ResolveFunc<T>, delay(reject) as RejectFunc); // 捕获 handler 中的异常,若有异常则直接将 Promise 状态改变为 rejected
} catch (err) {
(delay(reject) as RejectFunc)(err);
}
}
// 4. 处理 then 函数
then(onFulfilled?: onFulfilledFunc<T>, onRejected?: onRejectedFunc): MPromise<T> {
// 返回值永远为一个新的 Promise 对象
return new MPromise((resolve, reject) => {
// 5. 由于让上级 Promise 的状态变更或已完结的状态,通知到当前 Promise ?
// 6. 定义 _onFulfilled 函数,用于让上级 Promise 的状态变为 fulfilled 或已为 fulfilled 时,通知当前 Promise
const _onFulfilled: onFulfilledFunc<T> = (data) => {
if (onFulfilled && typeof onFulfilled === 'function') {
try {
const result = onFulfilled(data);
if (result && typeof result.then === 'function') {
result.then(resolve, reject); // onFulfilled 返回 Promise 时,该 Promise 对象变成为了本 Promise 对象的上级,故需要等该 Promise 完结时,再触发本 Promise 的 resolve 或 reject
} else {
resolve && resolve(result);
}
} catch (err) {
reject && reject(err); // onFulfilled 抛出异常时,则将本 Promise 变为 rejected 状态
}
} else {
resolve && resolve(data); // 当 onFulfilled 为非函数时,则直接将上级 Promise 的 data 传给本 Promise
}
}
// 7. 定义 _onRejected 函数,用于让上级 Promise 的状态变为 rejected 或已为 rejected 时,通知当前 Promise
const _onRejected: onRejectedFunc = (reason) => {
// 与上面的 _onFulfilled 思路类似
if (onRejected && typeof onRejected === 'function') {
try {
const result = onRejected(reason);
if (result && typeof result.then === 'function') {
result.then(resolve, reject); // onRejected 返回 Promise 时,该 Promise 对象变成为了本 Promise 对象的上级,故需要等该 Promise 完结时,再触发本 Promise 的 resolve 或 reject
} else {
resolve && resolve(result);
}
} catch (err) {
reject && reject(err); // onRejected 抛出异常时,则将本 Promise 变为 rejected 状态
}
} else {
reject && reject(reason); // 当 onRejected 为非函数时,则直接将上级 Promise 的 reason 传给本 Promise
}
}
switch (this.state) {
// 8. 上级 Promise 的状态已为 fulfilled 时,执行 then 的 onFulfilled 回调并触发本 Promise 的 resolve
case MPromiseState.fulfilled:
_onFulfilled(this.data);
break;
// 9. 上级 Promise 的状态已为 rejected 时,执行 then 的 onRejected 回调并触发本 Promise 的 reject
case MPromiseState.rejected:
_onRejected(this.reason);
break;
// 10. 上级 Promise 的状态为 pending 时,需要向上级 Promise 注册回调函数
case MPromiseState.pending:
this.onFulfilled = _onFulfilled; // 向上级 Promise 注册 onFulfilled 回调函数
this.onRejected = _onRejected; // 向上级 Promise 注册 onRejected 回调函数
break;
}
});
}
catch(onRejected?: onRejectedFunc): MPromise<T> {
// 11. catch 相当于关心上级 Promise 的 rejected 状态,故可以这样调用
return this.then(undefined, onRejected);
}
}
到此,一个 Promise 的实现最核心的问题基本已经完成。其他扩展就比较容易了,如
MPromise.resolve = function(data: T): MPromise<T> { return new MPromise((resolve) => resolve(data)); }
但是上面的代码仍然存在部分使用场景无法覆盖的问题,如:
const p = new MPromise((resolve) => resolve('a'));
p.then(x => console.log(`111 ${a}`));
p.then(x => console.log(`222 ${a}`));
那么,这里将永远只打印出来 222 a
,原因在于 onFulfilled 和 onRejected 回调函数被覆盖,解决这一问题,需要将 onFulfilled 和 onRejected 改造成数组。