mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Add function promiseSome
Co-Authored-By: Ludovico Granata <Ludogranata@gmail.com>
This commit is contained in:
parent
c13c03ef54
commit
0355673a0f
@ -325,6 +325,7 @@ export * from './util/FetchUtil';
|
||||
export * from './util/GuardedStream';
|
||||
export * from './util/HeaderUtil';
|
||||
export * from './util/PathUtil';
|
||||
export * from './util/PromiseUtil';
|
||||
export * from './util/QuadUtil';
|
||||
export * from './util/RecordObject';
|
||||
export * from './util/ResourceUtil';
|
||||
|
30
src/util/PromiseUtil.ts
Normal file
30
src/util/PromiseUtil.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const infinitePromise = new Promise<boolean>((): void => {});
|
||||
|
||||
/**
|
||||
* A function that simulates the Array.some behaviour but on an array of Promises.
|
||||
* Returns true if at least one promise returns true.
|
||||
* Returns false if all promises return false or error.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Predicates provided as input must be implemented considering
|
||||
* the following points:
|
||||
* 1. if they throw an error, it won't be propagated;
|
||||
* 2. throwing an error should be logically equivalent to returning false.
|
||||
*/
|
||||
export async function promiseSome(predicates: Promise<boolean>[]): Promise<boolean> {
|
||||
// These promises will only finish when their predicate returns true
|
||||
const infinitePredicates = predicates.map(async(predicate): Promise<boolean> => predicate.then(
|
||||
async(value): Promise<boolean> => value ? true : infinitePromise,
|
||||
async(): Promise<boolean> => infinitePromise,
|
||||
));
|
||||
|
||||
// Returns after all predicates are resolved
|
||||
const finalPromise = Promise.allSettled(predicates).then((results): boolean =>
|
||||
results.some((result): boolean => result.status === 'fulfilled' && result.value));
|
||||
|
||||
// Either one of the infinitePredicates will return true,
|
||||
// or finalPromise will return the result if none of them did or finalPromise was faster
|
||||
return Promise.race([ ...infinitePredicates, finalPromise ]);
|
||||
}
|
31
test/unit/util/PromiseUtil.test.ts
Normal file
31
test/unit/util/PromiseUtil.test.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { promiseSome } from '../../../src/util/PromiseUtil';
|
||||
|
||||
describe('PromiseUtil', (): void => {
|
||||
describe('#promiseSome', (): void => {
|
||||
const resultTrue = Promise.resolve(true);
|
||||
const resultFalse = Promise.resolve(false);
|
||||
const resultError = Promise.reject(new Error('generic error'));
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const resultInfinite = new Promise<boolean>((): void => {});
|
||||
|
||||
it('returns false if no promise is provided.', async(): Promise<void> => {
|
||||
await expect(promiseSome([])).resolves.toEqual(false);
|
||||
});
|
||||
|
||||
it('returns false if no promise returns true.', async(): Promise<void> => {
|
||||
await expect(promiseSome([ resultFalse, resultFalse, resultFalse ])).resolves.toEqual(false);
|
||||
});
|
||||
|
||||
it('returns true if at least a promise returns true.', async(): Promise<void> => {
|
||||
await expect(promiseSome([ resultFalse, resultTrue, resultFalse ])).resolves.toEqual(true);
|
||||
});
|
||||
|
||||
it('does not propagate errors.', async(): Promise<void> => {
|
||||
await expect(promiseSome([ resultError, resultFalse, resultFalse ])).resolves.toEqual(false);
|
||||
});
|
||||
|
||||
it('works with a combination of promises.', async(): Promise<void> => {
|
||||
await expect(promiseSome([ resultError, resultTrue, resultInfinite ])).resolves.toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user