Skip to content

Commit

Permalink
Support waiting for promise in Collector.wait
Browse files Browse the repository at this point in the history
  • Loading branch information
tshemsedinov committed Dec 16, 2023
1 parent 0ae1c82 commit f1b8b6e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
58 changes: 57 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Async collection is an utility to collect needed keys and signalize on done.
- `options.exact?: boolean`
- `options.timeout?: number`
- `set(key: string, value: unknown)`
- `wait(key: string, fn: AsyncFunction, ...args?: Array<unknown>)`
- `wait(key: string, fn: AsyncFunction | Promise<unknown>, ...args?: Array<unknown>)`
- `take(key: string, fn: Function, ...args?: Array<unknown>)`
- `collect(sources: Record<string, Collector>)`
- `fail(error: Error)`
Expand Down Expand Up @@ -92,6 +92,62 @@ dc.collect({ key1, key3 });
const result = await ac;
```

Complex example: compare `Promise.all` and `Collector` in next two examples:

```js
// Collect 4 keys from different contracts with Promise.all

const promise1 = new Promise((resolve, reject) => {
fs.readFile('README.md', (err, data) => {
if (err) return void reject(err);
resolve(data);
});
});

const promise2 = fs.promises.readFile('README.md');
const url = 'http://worldtimeapi.org/api/timezone/Europe';

const promise3 = fetch(url).then((data) => data.json());

const promise4 = new Promise((resolve) => {
setTimeout(() => {
resolve('value4');
}, 50);
});

const [key1, key2, key3, key4] = await Promise.all([
promise1,
promise2,
promise3,
promise4,
]);
const result = { key1, key2, key3, key4 };
console.log(result);
```

Compare with:

```js
// Collect 4 keys from different contracts with Collector

const dc = collect(['key1', 'key2', 'key3', 'key4']);

dc.take('key1', fs.readFile, 'README.md');

dc.wait('key2', fs.promises.readFile, 'README.md');

const url = 'http://worldtimeapi.org/api/timezone/Europe';
dc.wait(
'key3',
fetch(url).then((data) => data.json()),
);

setTimeout(() => dc.set('key4', 'value4'), 50);

const result = await dc;
console.log(result);
```

## Crypto utilities

- `cryptoRandom(min?: number, max?: number): number`
Expand Down
3 changes: 2 additions & 1 deletion lib/collector.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class Collector {
}

wait(key, fn, ...args) {
fn(...args).then(
const promise = fn instanceof Promise ? fn : fn(...args);
promise.then(
(data) => this.set(key, data),
(err) => this.fail(err),
);
Expand Down
6 changes: 5 additions & 1 deletion metautil.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,11 @@ export class Collector {
timeout: number;
constructor(keys: Array<string>, options?: CollectorOptions);
set(key: string, value: unknown): void;
wait(key: string, fn: AsyncFunction, ...args: Array<unknown>): void;
wait(
key: string,
fn: AsyncFunction | Promise<unknown>,
...args: Array<unknown>
): void;
take(key: string, fn: Function, ...args: Array<unknown>): void;
collect(sources: Record<string, Collector>): void;
fail(error: Error): void;
Expand Down
14 changes: 14 additions & 0 deletions test/collector.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,20 @@ metatests.test('Collector: wait', async (test) => {
test.end();
});

metatests.test('Collector: wait for promise', async (test) => {
const expectedResult = { key1: 'User: Marcus' };
const dc = collect(['key1']);

const promise = new Promise((resolve) => {
setTimeout(() => resolve('User: Marcus'), 100);
});
dc.wait('key1', promise);

const result = await dc;
test.strictSame(result, expectedResult);
test.end();
});

metatests.test('Collector: compose collect', async (test) => {
const expectedResult = { key1: { sub1: 11 }, key2: 2, key3: { sub3: 31 } };
const dc = collect(['key1', 'key2', 'key3']);
Expand Down

0 comments on commit f1b8b6e

Please sign in to comment.