diff --git a/README.md b/README.md index 4812411..063d915 100644 --- a/README.md +++ b/README.md @@ -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)` +- `wait(key: string, fn: AsyncFunction | Promise, ...args?: Array)` - `take(key: string, fn: Function, ...args?: Array)` - `collect(sources: Record)` - `fail(error: Error)` @@ -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` diff --git a/lib/collector.js b/lib/collector.js index 6e295e9..3d3402d 100644 --- a/lib/collector.js +++ b/lib/collector.js @@ -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), ); diff --git a/metautil.d.ts b/metautil.d.ts index 3b21e01..07859da 100644 --- a/metautil.d.ts +++ b/metautil.d.ts @@ -248,7 +248,11 @@ export class Collector { timeout: number; constructor(keys: Array, options?: CollectorOptions); set(key: string, value: unknown): void; - wait(key: string, fn: AsyncFunction, ...args: Array): void; + wait( + key: string, + fn: AsyncFunction | Promise, + ...args: Array + ): void; take(key: string, fn: Function, ...args: Array): void; collect(sources: Record): void; fail(error: Error): void; diff --git a/test/collector.js b/test/collector.js index 7121eed..c7b831c 100644 --- a/test/collector.js +++ b/test/collector.js @@ -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']);