Promises/A+ 规范文档
代码实现
enum States {
PENDING = "pending",
FULFILLED = "fulfilled",
REJECTED = "rejected",
}
interface Resolve<T> {
(value: T | PromiseLike<T>): void;
}
interface Reject {
(reason?: any): void;
}
interface Executor<T> {
(resolve: Resolve<T>, reject: Reject): void;
}
interface PromiseLike<T> {
then<TResult1 = T, TResult2 = never>(
onFulfilled?: ((value: T | PromiseLike<T>) => TResult1 | PromiseLike<TResult1>) | undefined | null,
onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
): PromiseLike<TResult1 | TResult2>;
}
export class MyPromise<T> {
private state: States = States.PENDING;
private onFulfilledCallbacks = [] as (() => void)[];
private onRejectedCallbacks = [] as (() => void)[];
private value!: T | PromiseLike<T>;
private reason: any;
constructor(executor: Executor<T>) {
try {
executor(this.resolve, this.reject);
} catch (e) {
this.reject(e);
}
}
private resolve: Resolve<T> = (value: T | PromiseLike<T>) => {
try {
setTimeout(() => {
if (this.state === States.PENDING) {
this.state = States.FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach((fn) => fn());
this.onFulfilledCallbacks = [];
}
});
} catch (e) {
this.reject(e);
}
};
private reject: Reject = (reason: any) => {
try {
setTimeout(() => {
if (this.state === States.PENDING) {
this.state = States.REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
this.onRejectedCallbacks = [];
}
});
} catch (e) {
this.reject(e);
}
};
then<TResult1 = T, TResult2 = never>(
onFulfilled?: ((value: T | PromiseLike<T>) => TResult1 | PromiseLike<TResult1>) | undefined | null,
onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
): MyPromise<TResult1 | TResult2> {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (val: T | PromiseLike<T>) => val as any;
onRejected =
typeof onRejected === "function"
? onRejected
: (r: any) => {
throw r;
};
const promise2 = new MyPromise<TResult1 | TResult2>((resolve: Resolve<TResult1 | TResult2>, reject: Reject) => {
if (this.state === States.FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled!(this.value);
this.resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
} else if (this.state === States.REJECTED) {
setTimeout(() => {
try {
let x = onRejected!(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
} else if (this.state === States.PENDING) {
this.onFulfilledCallbacks.push(() => {
try {
let x = onFulfilled!(this.value);
this.resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
this.onRejectedCallbacks.push(() => {
try {
let x = onRejected!(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
});
return promise2;
}
resolvePromise<T>(promise: MyPromise<T>, x: T | PromiseLike<T>, resolve: Resolve<T>, reject: Reject) {
if (promise === x) {
const e = new TypeError("TypeError: Circular reference");
reject(e);
}
let called = false;
if (x && (typeof x === "object" || typeof x === "function")) {
try {
const then = (x as PromiseLike<T>).then;
if (typeof then === "function") {
then.call(
x,
(y: T | PromiseLike<T>) => {
if (called) return;
called = true;
this.resolvePromise(promise, y, resolve, reject);
},
(r: any) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
}
测试流程
测试工具文档:Promises/A+ Compliance Test Suite
为了使用官方工具进行测试,需要在程序的最后添加如下代码:
MyPromise.defer = MyPromise.deferred = function () {
let deferred: any = {};
deferred.promise = new MyPromise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
};
export = MyPromise;
将ts代码编译为js
tsc promise.ts
运行测试
npx promises-aplus-tests promise.js
测试结果:
参考文章
- Promise的源码实现(完美符合Promise/A+规范)
- 实现一个TS版,符合 Promise/A+规范的 Promise
|