@msom/common
Version:
@msom/common
397 lines (363 loc) • 10.7 kB
text/typescript
import { Nullable, createFunction, tryCall } from "../../global";
import { nextTick } from "../nextTick";
import { OcPromiseRejectError } from "./OcPromiseError";
import {
CANCELED,
Cancel,
Canceled,
FULFILLED,
Fulfilled,
OcPromiseExecutor,
OcPromiseLike,
OcPromiseStatus,
PENDDING,
PromiseLike,
REJECTED,
Reject,
Rejected,
Resolve,
} from "./types";
import { isOcPromiseLike, isPromiseLike } from "./utils";
/**
* OcPromise 类 - 扩展的 Promise 实现,支持取消操作
* @template R - 成功状态的返回值类型
* @template E - 错误类型,默认为 OcPromiseRejectError
* @template C - 取消操作的原因类型
*/
export class OcPromise<
R,
E extends Error | unknown = OcPromiseRejectError,
C = unknown
> implements OcPromiseLike<R>
{
/** 当前 Promise 的状态 */
declare status: OcPromiseStatus;
/** 处理函数队列 */
private declare handlers: {
resolve: Resolve<unknown>;
reject: Reject<Error | unknown>;
cancel: Cancel<unknown>;
onfulfilled: Nullable | createFunction<[R, unknown]>;
onrejected: Nullable | createFunction<[E | unknown, unknown]>;
oncanceled: Nullable | createFunction<[C, unknown]>;
}[];
/** 存储当前值(完成值/错误/取消原因) */
declare data: R | E | C;
/** 父 Promise,用于取消操作的传播 */
private declare parrent:
| OcPromise<unknown, Error | unknown, unknown>
| undefined;
/**
* 创建 OcPromise 实例
* @param executor 执行器函数,接收 resolve、reject 和 cancel 函数
*/
constructor(executor: OcPromiseExecutor<R, E, C>) {
// 初始化为等待状态
this.status = PENDDING;
// 初始化处理函数队列
this.handlers = [];
// 创建 resolve 处理函数
const resolve: Resolve<R> = (data: R) => {
if (isOcPromise(data) || isOcPromiseLike(data)) {
data.then(resolve, reject, cancel);
} else if (isPromiseLike(data)) {
data.then(resolve, reject);
} else {
// 将状态改为已完成
this.changeStatus(FULFILLED, data);
}
};
// 创建 reject 处理函数
const reject: Reject<E | unknown> = (reason) => {
// 将状态改为已拒绝
this.changeStatus(REJECTED, reason as E);
};
// 创建 cancel 处理函数
const cancel: Cancel<C> = (reason: C) => {
// 将状态改为已取消
this.changeStatus(CANCELED, reason);
};
try {
// 执行传入的执行器函数
executor(resolve, reject, cancel);
} catch (e: unknown) {
// 如果执行器抛出错误,将 Promise 状态改为已拒绝
reject(e);
}
}
/**
* 添加完成、错误和取消的处理函数
*/
then<TR = R, TE = never, TC = never>(
onfulfilled?:
| Nullable
| createFunction<[R, OcPromiseLike<TR> | PromiseLike<TR> | TR]>,
onrejected?:
| Nullable
| createFunction<[E, OcPromiseLike<TE> | PromiseLike<TE> | TE]>,
oncanceled?:
| Nullable
| createFunction<[C, OcPromiseLike<TC> | PromiseLike<TC> | TC]>
): OcPromise<TR | TE | TC> {
// 创建新的 OcPromise 实例
const res = new OcPromise<TR | TE | TC>((resolve, reject, cancel) => {
// 将处理函数添加到队列
this.handlers.push({
resolve,
reject,
cancel,
onfulfilled,
onrejected,
oncanceled,
});
// 尝试执行处理函数队列
this._runThens();
});
// 设置父 Promise,用于取消操作的传播
res.parrent = this;
return res;
}
/**
* 改变 Promise 状态
* @private
* @template T - 目标状态类型
* @template D - 数据类型
* @param status - 新状态
* @param data - 相关数据
*/
private changeStatus<
T extends OcPromiseStatus,
D extends R | E | C = T extends Fulfilled
? R
: T extends Rejected
? R
: T extends Canceled
? C
: never
>(status: T, data: D) {
// 只有在等待状态时才能改变状态
if (this.status !== PENDDING) {
return;
}
// 更新状态和数据
this.status = status;
this.data = data;
// 执行处理函数队列
this._runThens();
}
/**
* 执行处理函数队列
* @private
*/
private _runThens() {
// 只有在非等待状态时才执行处理函数
if (this.status === PENDDING) {
return;
}
// 依次处理队列中的处理函数
while (this.handlers.length) {
// 取出队列中的第一个处理函数组
const handler = this.handlers.shift()!;
const { resolve, reject, cancel, onfulfilled, onrejected, oncanceled } =
handler;
// 根据当前状态选择要执行的处理函数,未传对应处理函数则状态穿透
const exe =
this.status === FULFILLED
? onfulfilled
? // 如果有完成处理函数,则调用它
() => tryCall(onfulfilled, [this.data as R])
: // 否则直接调用 resolve
(resolve(this.data), undefined)
: this.status === REJECTED
? onrejected
? // 如果有拒绝处理函数,则调用它
() => tryCall(onrejected, [this.data as E])
: // 否则直接调用 reject
(reject(this.data), undefined)
: oncanceled
? // 如果有取消处理函数,则调用它
() => tryCall(oncanceled, [this.data as C])
: // 否则直接调用 cancel
(cancel(this.data), undefined);
// 如果没有要执行的函数thenable回调,继续下一个
if (!exe) continue;
// 创建异步任务
const task = () => {
try {
// 执行处理函数
const data = exe();
if (isOcPromise(data) || isOcPromiseLike(data)) {
// 如果返回值是 OcPromise,则链接它的处理函数
nextTick(() => {
data.then(
resolve,
reject,
(reason) => (this.cancel(reason as C), cancel(reason as C))
);
});
} else if (isPromiseLike(data)) {
// 如果返回值是 Promise,则链接它的处理函数
nextTick(() => {
data.then(resolve, reject);
});
} else {
// 其他情况直接 resolve
resolve(data);
}
} catch (e) {
// 如果执行过程中出错,则 reject
reject(e);
}
};
// 将任务加入下一个事件循环
nextTick(task);
}
}
/**
* 取消 Promise
* @param reason - 取消原因
*/
cancel(reason: C) {
if (this.parrent && this.parrent.status === PENDDING) {
this.parrent.cancel(reason);
} else {
this.changeStatus(CANCELED, reason);
}
}
/**
* 等待所有 Promise 完成
* @static
* @template T - 元素类型
* @param proms - Promise 或值的可迭代对象
* @returns 包含所有结果的 Promise
*/
static all<T>(
proms: Iterable<T | OcPromiseLike<Awaited<T>>>
): OcPromise<Awaited<T>[]> {
// 存储所有 Promise 的结果
const result: Awaited<T>[] = [];
return new OcPromise<Awaited<T>[]>((resolve, reject, cancel) => {
// 处理单个 Promise 完成的情况
const _resolve = (data: Awaited<T>, index: number) => {
// 将结果存储到对应位置
result[index] = data;
finished++;
// 如果所有 Promise 都完成,则 resolve
if (finished === i) resolve(result);
};
let i: number = 0, // Promise 总数
finished: number = 0; // 已完成的 Promise 数量
// 遍历可迭代对象
const iterator = proms[Symbol.iterator]();
let next: ReturnType<typeof iterator.next> = iterator.next();
while (!next.done) {
const j = i;
i++;
const { value } = next;
if (isOcPromise<Awaited<T>, Error, Error>(value)) {
// 处理 OcPromise
value.then((data) => _resolve(data, j), reject, cancel);
} else if (isPromiseLike<Awaited<T>>(value)) {
// 处理普通 Promise
value.then((data) => _resolve(data, j), reject);
} else {
// 处理非 Promise 值
result[j] = value as Awaited<T>;
finished++;
}
next = iterator.next();
}
// 如果所有值都已处理完成,直接 resolve
if (finished === i) {
resolve(result);
}
});
}
/**
* 创建一个已完成的 Promise
* @static
* @template T - 值的类型
* @param value - 要解析的值
*/
static resolve<T extends void | unknown = void>(
value: T
): OcPromise<Awaited<T>> {
if (isOcPromise<Awaited<T>>(value)) {
return value;
}
if (isOcPromiseLike<Awaited<T>>(value)) {
return new OcPromise<Awaited<T>>((resolve, reject, cancel) => {
value.then(resolve, reject, cancel);
});
}
if (isPromiseLike<Awaited<T>>(value)) {
return new OcPromise<Awaited<T>>((resolve, reject) => {
value.then(resolve, reject);
});
}
return new OcPromise<Awaited<T>>((resolve) => {
resolve(value as Awaited<T>);
});
}
/**
* 创建一个已拒绝的 Promise
* @static
* @template E - 错误类型
* @param reason - 拒绝原因
*/
static reject<E extends OcPromiseRejectError | unknown = unknown>(
reason: E
): OcPromise<unknown, E> {
return new OcPromise((_, reject) => {
reject(reason);
});
}
/**
* 添加取消处理函数
* @param oncanceled - 取消处理函数
*/
canceled(oncanceled: Cancel<C>) {
return this.then(null, null, oncanceled);
}
/**
* 添加错误处理函数
* @param onRejected - 错误处理函数
*/
catch(onRejected: Reject<E>) {
return this.then(null, onRejected, null);
}
/** 获取当前数据 */
getData() {
return this.data;
}
/** 获取当前状态 */
getStatus() {
return this.status;
}
}
/**
* 检查值是否为 OcPromise 实例
* @template PR - Promise 结果类型
* @template PE - Promise 错误类型
* @template PC - Promise 取消类型
* @param data - 要检查的值
*/
export function isOcPromise<
PR,
PE extends Error | unknown = Error,
PC = unknown
>(data: unknown): data is OcPromise<PR, PE, PC> {
return data instanceof OcPromise;
}
OcPromise.resolve("A")
.then((data) => {
return OcPromise.resolve<"C">("C");
})
.then((data) => {
data;
});
Promise.resolve()
.then(null, () => {
return new Promise<"B">(() => {});
})
.then((data) => {});