Skip to content

Instantly share code, notes, and snippets.

@doronguttman
Created December 1, 2022 20:16
Show Gist options
  • Save doronguttman/aeeb50312773448cd1121da51a1d164a to your computer and use it in GitHub Desktop.
Save doronguttman/aeeb50312773448cd1121da51a1d164a to your computer and use it in GitHub Desktop.
Promise.raceTo (race with predicate)
interface PromiseConstructor {
/**
* Creates a Promise that is resolved with the value of the first resolved Promise that matches the predicate or rejected if any of the Promises are rejected.
* @param promises An array of Promises.
* @param [predicate] Optional. A function that is called with the result of each Promise. If the function returns true, the Promise is considered to be resolved. If no predicate is provided, the first truthy resolved Promise is returned.
* @returns A new Promise which is resolved with the value of the first resolved Promise that matches the predicate.
*/
raceTo<T extends readonly unknown[] | []>(promises: T, predicate?: (result: Awaited<T[number]>) => boolean): Promise<Awaited<T[number]> | undefined>;
}
Promise.raceTo ??= function raceTo<T extends readonly unknown[] | []>(promises: T, predicate: (result: Awaited<T[number]>) => boolean = (result) => !!result): Promise<Awaited<T[number]> | undefined> {
return new Promise<Awaited<T[number]> | undefined>(async (resolve, reject) => {
try {
await Promise.allSettled(
promises.map(async (promise: T[number]) => {
try {
const result = await promise;
if (predicate(result)) {
resolve(result);
}
} catch (error) {
reject(error instanceof Error ? error : new AggregateError([error]));
}
})
);
} finally {
resolve(undefined);
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment