遵循 Promise/A+ 标准,手写实现一个 Promise 函数,包含以下功能函数:
- Promise.reject
- Promise.all
- Promise.race
- Promise.prototype.catch
- Promise.prototype.finally
- Promise.allSettled
Typescript 实现 ,附注释:
const PENDING = "pending" as const;
const FULFILLED = "fulfilled" as const;
const REJECTED = "rejected" as const;
type PromiseStatus = typeof PENDING | typeof FULFILLED | typeof REJECTED;
/**
* 自定义Promise实现(遵循Promise/A+规范)
* @template T Promise解析值的类型
*/
export class PromiseTest<T = unknown> {
// 当前Promise状态(初始为pending)
private status: PromiseStatus = PENDING;
// 成功状态时的值(仅当status为fulfilled时有值),默认为 undefined
private value: T | undefined = undefined;
// 失败状态时的原因(仅当status为rejected时有值),默认为 undefined
private reason: unknown = undefined;
// 存储成功回调的数组(用于pending状态时暂存回调)
private onResolvedCallbacks: Array<() => void> = [];
// 存储失败回调的数组(用于pending状态时暂存回调)
private onRejectedCallbacks: Array<() => void> = [];
/**
* 构造函数,接收执行器函数
* @param executor 执行器函数,接收resolve和reject作为参数
* @throws 执行器同步抛出异常时会直接调用reject
*/
constructor(
executor: (
resolve: (value: T) => void,
reject: (reason: unknown) => void
) => void
) {
// resolve函数(Promise/A+ 2.1.2 成功状态转换)
const resolve = (value: T) => {
// 仅当状态为pending时允许转换
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
// 触发所有暂存的成功回调(Promise/A+ 2.2.6.1 顺序执行)
this.onResolvedCallbacks.forEach((fn) => fn());
}
};
// reject函数(Promise/A+ 2.1.3 失败状态转换)
const reject = (reason: unknown) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
// 触发所有暂存的失败回调(Promise/A+ 2.2.6.2 顺序执行)
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
// 执行器可能同步抛出异常(Promise/A+ 2.1.3.2 异常处理)
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
/**
* 解析then回调的返回值x,决定新Promise的状态(Promise/A+ 2.3)
* @template U 新Promise解析值的类型
* @param promise2 新Promise实例(需要避免循环引用)
* @param x then回调的返回值(可能是普通值、Promise或thenable)
* @param resolve 新Promise的resolve函数
* @param reject 新Promise的reject函数
*/
private static resolvePromise<U>(
promise2: PromiseTest<U>,
x: unknown,
resolve: (value: U) => void,
reject: (reason: unknown) => void
) {
// 循环引用检测(Promise/A+ 2.3.1)
if (promise2 === x) {
return reject(new TypeError("Chaining cycle detected for promise"));
}
// 防止重复调用resolve/reject
let called = false;
try {
// 处理thenable对象(Promise/A+ 2.3.3)
if ((typeof x === "object" && x !== null) || typeof x === "function") {
const then = (x as any).then;
// 如果x是具有then方法的对象/函数(thenable)
if (typeof then === "function") {
// 调用x.then(不要写成 x.then,直接 then.call 就可以了 因为 x.then 会再次取值,Object.defineProperty),传递新的resolve/reject(Promise/A+ 2.3.3.3)
then.call(
x,
(y: unknown) => {
if (called) return; // 已调用过,直接返回
called = true;
// 递归解析y(可能是另一个Promise)
PromiseTest.resolvePromise(promise2, y, resolve, reject);
},
(r: unknown) => {
if (called) return;
called = true;
// 失败时直接拒绝新Promise
reject(r);
}
);
} else {
// x是对象/函数但无then方法:直接成功(Promise/A+ 2.3.3.4)
resolve(x as U);
}
} else {
// 处理普通值,如果 x 是个普通值就直接返回 resolve 作为结果(Promise/A+ 2.3.4)
resolve(x as U);
}
} catch (err) {
// 异常处理(Promise/A+ 2.3.3.2)
if (called) return;
called = true;
reject(err);
}
}
/**
* 注册成功/失败回调,返回新的Promise实例
* @template U 成功回调返回值类型
* @template V 失败回调返回值类型
* @param onFulfilled 成功回调(可选,默认透传值)
* @param onRejected 失败回调(可选,默认抛异常)
* @returns 新的Promise实例,状态由回调执行结果决定
*/
then<U = T, V = never>(
onFulfilled?: (value: T) => U | PromiseLike<U>,
onRejected?: (reason: unknown) => V | PromiseLike<V>
): PromiseTest<U | V> {
// 处理未传回调的情况(Promise/A+ 2.2.1 可选回调)
const _onFulfilled =
typeof onFulfilled === "function"
? onFulfilled
: (value: T) => value as unknown as U; // 默认透传值
const _onRejected =
typeof onRejected === "function"
? onRejected
: (reason: unknown) => {
throw reason;
}; // 默认抛异常
// 创建新Promise实例(Promise/A+ 2.2.7 链式调用)
const promise2 = new PromiseTest<U | V>((resolve, reject) => {
// 成功处理函数
const handleFulfilled = () => {
// 异步执行回调(Promise/A+ 2.2.4 异步要求)
setTimeout(() => {
try {
// 执行成功回调并获取返回值x(Promise/A+ 2.2.7.1)
const x = _onFulfilled(this.value!);
// 解析x并决定promise2的状态(关键逻辑)
PromiseTest.resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 回调抛出异常时,promise2拒绝(Promise/A+ 2.2.7.2)
reject(e);
}
}, 0);
};
// 失败处理函数
const handleRejected = () => {
setTimeout(() => {
try {
const x = _onRejected(this.reason!);
PromiseTest.resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
};
// 根据当前状态分支处理
if (this.status === FULFILLED) {
// 已成功:直接执行成功处理
handleFulfilled();
} else if (this.status === REJECTED) {
// 已失败:直接执行失败处理
handleRejected();
} else {
// 未决状态(pending):暂存回调,待状态变更时触发
this.onResolvedCallbacks.push(handleFulfilled);
this.onRejectedCallbacks.push(handleRejected);
}
});
return promise2;
}
/**
* 返回一个已解决的Promise实例(ES6规范)
* @param value 要解决的值(可能是普通值、Promise或thenable)
* @returns 新的Promise实例
*/
static resolve<U>(value: U | PromiseLike<U>): PromiseTest<U> {
// 如果value本身是PromiseTest实例,直接返回
if (value instanceof PromiseTest) {
return value;
}
// 否则创建新Promise并解析value
return new PromiseTest<U>((resolve) => {
// 调用resolvePromise处理thenable
PromiseTest.resolvePromise(
new PromiseTest<U>((resolveInner) => {
// 避免立即执行
resolve = resolveInner; // 替换为外部resolve
}),
value,
resolve,
(err) => {
throw err;
}
);
});
}
/**
* 返回一个已拒绝的Promise实例(ES6规范)
* @param reason 拒绝的原因
* @returns 新的Promise实例
*/
static reject<U>(reason: unknown): PromiseTest<U> {
return new PromiseTest<U>((_, reject) => {
reject(reason);
});
}
/**
* 等待所有Promise完成,返回结果数组(ES6规范)
* @param promises 可迭代的Promise数组
* @returns 新的Promise实例,解决时为结果数组,拒绝时为第一个拒绝的原因
*/
static all<U>(promises: Iterable<PromiseLike<U>>): PromiseTest<U[]> {
return new PromiseTest<U[]>((resolve, reject) => {
const results: U[] = [];
let count = 0;
const iterable = Array.from(promises);
const len = iterable.length;
// 处理空数组情况(直接解决)
if (len === 0) {
resolve([]);
return;
}
iterable.forEach((promise, index) => {
PromiseTest.resolve(promise).then(
(value) => {
results[index] = value;
count++;
if (count === len) {
resolve(results);
}
},
(err) => reject(err) // 任意一个拒绝则整体拒绝
);
});
});
}
/**
* 返回第一个完成(解决或拒绝)的Promise的结果(ES6规范)
* @param promises 可迭代的Promise数组
* @returns 新的Promise实例,解决/拒绝取决于第一个完成的Promise
*/
static race<U>(promises: Iterable<PromiseLike<U>>): PromiseTest<U> {
return new PromiseTest<U>((resolve, reject) => {
Array.from(promises).forEach((promise) => {
PromiseTest.resolve(promise).then(resolve, reject);
});
});
}
/**
* 等待所有Promise完成,返回包含每个结果状态的数组(ES2020规范)
* @param promises 可迭代的Promise数组
* @returns 新的Promise实例,解决时为{ status: 'fulfilled', value }或{ status: 'rejected', reason }的数组
*/
static allSettled<U>(
promises: Iterable<PromiseLike<U>>
): PromiseTest<
Array<
| { status: "fulfilled"; value: U }
| { status: "rejected"; reason: unknown }
>
> {
return new PromiseTest((resolve) => {
const results: Array<
| { status: "fulfilled"; value: U }
| { status: "rejected"; reason: unknown }
> = [];
let count = 0;
const iterable = Array.from(promises);
const len = iterable.length;
if (len === 0) {
resolve([]);
return;
}
iterable.forEach((promise, index) => {
PromiseTest.resolve(promise).then(
(value) => {
results[index] = { status: "fulfilled", value };
count++;
if (count === len) resolve(results);
},
(reason) => {
results[index] = { status: "rejected", reason };
count++;
if (count === len) resolve(results);
}
);
});
});
}
/**
* 注册拒绝回调(ES6规范,等价于then(undefined, onRejected))
* @param onRejected 拒绝时的回调函数
* @returns 新的Promise实例
*/
catch<V = never>(
onRejected?: (reason: unknown) => V | PromiseLike<V>
): PromiseTest<T | V> {
return this.then(undefined, onRejected);
}
/**
* 注册最终回调(ES2018规范,无论解决/拒绝都会执行)
* @param onFinally 最终执行的回调函数(无参数)
* @returns 新的Promise实例,状态与原Promise一致
*/
finally(onFinally: () => void): PromiseTest<T> {
return this.then(
(value) => {
onFinally();
return value;
},
(reason) => {
onFinally();
throw reason;
}
);
}
}