Я недавно переключился с JavaScript на TypeScript, что действительно здорово. Во время моей ежедневной работы мне было интересно, как Promises работает под капотом, и после короткого поиска в Google я нашел эту прекрасную статью: https://softchris.github.io/pages/javascript-promises.html#why. Тогда я подумал, что было бы неплохо преобразовать это в TypeScript. Ну, я получил его на работу, как вы можете видеть ниже. Одна вещь, которую я не мог исправить, это то, что data
, onSuccess
и onFailure
все еще имеют any
вместо generi c в then<R>(){}
. Тот факт, что error
является any
, был преднамеренным.
Так может кто-нибудь помочь мне исправить это? Для игры с кодом вы можете использовать https://stackblitz.com/edit/swear-ts.
Большое спасибо! :)
type Resolver<T> = (x: T) => void;
type Rejecter = (x: any) => void;
type Factory<T> = (resolve: Resolver<T>, reject?: Rejecter) => void;
type OnSuccessFn<T, R> = (data: T) => R;
type OnFailureFn<R> = (error: any) => R;
class Swear<T = any> {
private data: any;
private resolveWasInvoked = false;
private errorWasHandled = false;
private onSuccess: OnSuccessFn<T, any>;
private onFailure?: OnFailureFn<any>;
constructor(
private factory: Factory<T>,
private error: null | Error = null
) { }
private resolve(data: T): void {
if (!this.error) {
const result = this.onSuccess(data);
if (result) {
this.data = result;
}
this.resolveWasInvoked = true;
}
}
private reject(error: any): void {
if (!this.resolveWasInvoked) {
this.error = error;
if (this.onFailure) {
const result = this.onFailure(error);
if (result) {
this.data = result;
}
this.errorWasHandled = true;
}
}
}
public then<R>(
OnSuccessFn: OnSuccessFn<T, R>,
OnFailureFn?: OnFailureFn<R>
): Swear<R> {
this.onSuccess = OnSuccessFn;
this.onFailure = OnFailureFn;
this.factory(
(data: T): void => this.resolve(data),
(error: any): void => this.reject(error),
)
return new Swear<R>((resolve) => {
resolve(<R>this.data);
}, !this.errorWasHandled ? this.error : null);
}
catch(catchFn: (error: any) => void): void {
if (!this.errorWasHandled && this.error) {
catchFn(this.error);
}
}
}
const swear: Swear<string> = new Swear((resolve, reject) => {
resolve('Hello');
// reject('Ups..');
})
swear
.then(data => data + ' World!')
// .then(data => data.length)
.then(data => console.info(data))
.catch(error => console.error(`Catched: ${error}`));