export interface IResolve { (value?: T | PromiseLike): void; } export interface IReject { (reason?: any): void; } export type TDeferredStatus = 'pending' | 'fulfilled' | 'rejected'; export class Deferred { public promise: Promise; public resolve: IResolve; public reject: IReject; public status: TDeferredStatus; public startedAt: number; public stoppedAt: number; public get duration(): number { if (this.stoppedAt) { return this.stoppedAt - this.startedAt; } else { return Date.now() - this.startedAt; } } constructor() { this.promise = new Promise((resolve, reject) => { this.resolve = (valueArg: T | PromiseLike) => { this.status = 'fulfilled'; this.stoppedAt = Date.now(); resolve(valueArg); }; this.reject = (reason: any) => { this.status = 'rejected'; this.stoppedAt = Date.now(); reject(reason); }; this.startedAt = Date.now(); this.status = 'pending'; }); } } export const defer = () => { return new Deferred(); }; /** * Creates a new resolved promise for the provided value. */ export const resolvedPromise = (value?: T): Promise => { return Promise.resolve(value); }; /** * Creates a new rejected promise for the provided reason. */ export const rejectedPromise = (err) => { return Promise.reject(err); }; interface IAsyncFunction { (someArg: T): Promise; } /** * accepts an array of inputs and a function that accepts the input. * runs all items with the function and returns the result array when all items have run * @param inputArg * @param functionArg */ export const map = async (inputArg: T[], functionArg: IAsyncFunction) => { const promiseArray: Promise[] = []; const resultArray = []; for (const item of inputArg) { const promise: Promise = functionArg(item); promiseArray.push(promise); promise.then((x) => { resultArray.push(x); }); } await Promise.all(promiseArray); return resultArray; }; export const timeoutWrap = (ms, promise) => { return new Promise((resolve, reject) => { setTimeout(() => { reject(new Error('timeout')); }, ms); promise.then(resolve, reject); }); };