import { MyPromise } from './my-promise';
describe('MyPromise', () => {
it('should resolve with a given value', (done) => {
const promise = new MyPromise((resolve) => {
resolve('Hello world');
});
promise.then((value) => {
expect(value).toBe('Hello world');
done();
});
});
it('should handle asynchronous resolution', (done) => {
const promise = new MyPromise((resolve) => {
setTimeout(() => {
resolve('Async Hello, World!');
}, 100);
});
promise.then((value) => {
expect(value).toBe('Async Hello, World!');
done();
});
});
it('should handle rejection', (done) => {
const promise = new MyPromise((resolve, reject) => {
reject(new Error('Rejected'));
});
promise.catch((error) => {
expect(error).toEqual(new Error('Rejected'));
done();
});
});
it('should handle async rejection', (done) => {
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Rejected'));
}, 100);
});
promise.catch((error) => {
expect(error).toEqual(new Error('Rejected'));
done();
});
});
it('should support chaining with .then', (done) => {
const promise = new MyPromise((resolve) => {
resolve(1);
});
promise
.then((value) => value + 1)
.then((value) => {
expect(value).toBe(2);
done();
});
});
});
/* eslint-disable @typescript-eslint/no-explicit-any */
export class MyPromise {
private state: 'pending' | 'fulfilled' | 'rejected' = 'pending';
private value = undefined; // 成功后的值
private reason = undefined; // 失败后的原因
private onResolveCallbacks = []; // pending 状态下,存储成功的回调
private onRejectCallbacks = []; // pending 状态下,存储失败的回调
constructor(
executor: (
resolve: (value: unknown) => void,
reject: (reason?: any) => void
) => void
) {
const resolve = (value: any) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onResolveCallbacks.forEach((fn) => fn(this.value));
}
};
const reject = (reason: any) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectCallbacks.forEach((fn) => fn(this.reason));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled: (value: any) => void, onRejected?: (reason: any) => void) {
return new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
const result = onFulfilled(this.value);
resolve(result);
}
if (this.state === 'pending') {
this.onResolveCallbacks.push(onFulfilled);
this.onRejectCallbacks.push(onRejected);
}
if (this.state === 'rejected') {
const result = onRejected(this.reason);
reject(result);
}
});
}
catch(onRejected?: (reason: any) => void) {
this.then(null, onRejected);
}
}