Skip to content

Commit 55bd3bb

Browse files
feat(Promise): added tryOneByOne
1 parent 0e6850f commit 55bd3bb

File tree

5 files changed

+140
-0
lines changed

5 files changed

+140
-0
lines changed

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,23 @@ const promise = anAsyncCall();
340340
const [error, result] = await tryCatch(promise);
341341
```
342342

343+
#### [Try One By One](https://thalesrc.github.io/js-utils/modules/_promise_try_one_by_one_.html)
344+
Tries a set of promises one by one with given order. Breaks the call when a promise resolved. Otherwise keeps trying incoming promises until the list is finished.
345+
346+
```typescript
347+
import { tryOneByOne } from "@thalesrc/js-utils/promise";
348+
349+
async function fooFunction() {
350+
const foo = await tryOneByOne([
351+
() => someCall(),
352+
(err) => anotherCall(),
353+
(err) => fooPromise()
354+
]);
355+
356+
// do stuff
357+
}
358+
```
359+
343360
### String
344361

345362
#### [Limit](https://thalesrc.github.io/js-utils/modules/_string_limit_.html)

src/promise/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './never';
22
export * from './revert';
33
export * from './try-catch';
4+
export * from './try-one-by-one';
45
export * from './timeout';

src/promise/static/try-one-by-one.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { tryOneByOne } from '../try-one-by-one';
2+
3+
declare global {
4+
export interface PromiseConstructor {
5+
/**
6+
* #### Try One By One
7+
* Tries a set of promises one by one with given order. Breaks the call when a promise resolved. Otherwise keeps trying incoming promises until the list is finished.
8+
*
9+
* * * *
10+
* Example:
11+
* ```typescript
12+
* import "@thalesrc/js-utils/promise/static/try-one-by-one";
13+
*
14+
* async function fooFunction() {
15+
* const foo = await Promise.tryOneByOne([
16+
* () => someCall(),
17+
* (err) => anotherCall(),
18+
* (err) => fooPromise()
19+
* ]);
20+
*
21+
* // do stuff
22+
* }
23+
* ```
24+
* * * *
25+
*/
26+
tryOneByOne: typeof tryOneByOne;
27+
}
28+
}
29+
30+
Promise.tryOneByOne = tryOneByOne;

src/promise/try-one-by-one.spec.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import 'jest';
2+
3+
import { tryOneByOne } from './try-one-by-one';
4+
5+
class CustomError {
6+
constructor(public message: string) {}
7+
}
8+
9+
describe('TryOneByOne Function', () => {
10+
it('should resolve if a promise resolved', done => {
11+
tryOneByOne([Promise.resolve('foo')])
12+
.then(res => {
13+
expect(res).toBe('foo');
14+
done();
15+
})
16+
.catch(err => {
17+
throw new CustomError("didn't resolve");
18+
});
19+
});
20+
21+
it('should try the next promise when the first threw error', done => {
22+
tryOneByOne([
23+
Promise.reject('foo'),
24+
Promise.resolve('bar'),
25+
])
26+
.then(res => {
27+
expect(res).toBe('bar');
28+
done();
29+
})
30+
.catch(err => {
31+
throw new CustomError("didn't resolve");
32+
});
33+
});
34+
});

src/promise/try-one-by-one.ts

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* #### Try One By One
3+
*
4+
* Tries a set of promises one by one with given order. Breaks the call when a promise resolved. Otherwise keeps trying incoming promises until the list is finished.
5+
*
6+
* * * *
7+
* Example:
8+
* ```typescript
9+
* import { tryOneByOne } from "@thalesrc/js-utils/promise";
10+
*
11+
* async function fooFunction() {
12+
* const foo = await tryOneByOne([
13+
* () => someCall(),
14+
* (err) => anotherCall(),
15+
* (err) => fooPromise()
16+
* ]);
17+
*
18+
* // do stuff
19+
* }
20+
*
21+
* ```
22+
*
23+
* Static Example:
24+
* ```typescript
25+
* import "@thalesrc/js-utils/promise/static/try-one-by-one";
26+
*
27+
* async function fooFunction() {
28+
* const foo = await Promise.tryOneByOne([
29+
* () => someCall(),
30+
* (err) => anotherCall(),
31+
* (err) => fooPromise()
32+
* ]);
33+
*
34+
* // do stuff
35+
* }
36+
*
37+
* ```
38+
* * * *
39+
* @param promises List of promises to try one by one with the order
40+
* @returns
41+
*/
42+
export async function tryOneByOne<T>(promises: Array<Promise<T> | ((lastError: unknown) => Promise<T>)>): Promise<T> {
43+
return await tryPromises([...promises], null);
44+
}
45+
46+
async function tryPromises<T>(promises: Array<Promise<T> | ((lastError: unknown) => Promise<T>)>, lastError: unknown): Promise<T> {
47+
const promiseFn = promises.shift();
48+
49+
if (!promiseFn) throw lastError;
50+
51+
try {
52+
const promise = typeof promiseFn === "function" ? promiseFn(lastError) : promiseFn;
53+
54+
return await promise;
55+
} catch (err) {
56+
return tryPromises(promises, err);
57+
}
58+
}

0 commit comments

Comments
 (0)