type SequenceableFunction = () => Promise; /** * Run an array of functions that return promises in sequence */ export const sequence = async (fns: SequenceableFunction[]): Promise => { await fns.reduce(async (prev, next) => { await prev.then(next); }, Promise.resolve()); /** * This additional await ensures this function won't return until after the * last `SequenceableFunction` also returns. * * @see[the javascript event loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/) * for details */ await new Promise((resolve) => setTimeout(resolve, 0)); }; /** * Like {@link Promise.all}, but ensures that all promises finish and rejects if * at least one of the proces rejects with the reason. If all promises are * successful, @returns {T[]} of the promises in the correct order. */ export const allComplete = async (args: Array): Promise[]> => { return Promise.allSettled(args) .then((results) => { const rejected = results.find( (result): result is PromiseRejectedResult => result.status === 'rejected' ); if (rejected) return Promise.reject(rejected.reason); return results; }) .then((results: PromiseSettledResult[]) => { return results.filter( (result): result is PromiseFulfilledResult => result.status === 'fulfilled' ); }) .then((results) => { return results.map(({ value }) => value); }); };