diff --git a/README.md b/README.md index 369e6fa..dc34561 100644 --- a/README.md +++ b/README.md @@ -314,7 +314,7 @@ Loads multiple keys, promising an array of values: const [ a, b ] = await myLoader.loadMany([ 'a', 'b' ]) ``` -This is equivalent to the more verbose: +This is similar to the more verbose: ```js const [ a, b ] = await Promise.all([ @@ -323,6 +323,15 @@ const [ a, b ] = await Promise.all([ ]) ``` +However it is different in the case where any load fails. Where +Promise.all() would reject, loadMany() always resolves, however each result +is either a value or an Error instance. + +```js +var [ a, b, c ] = await myLoader.loadMany([ 'a', 'b', 'badkey' ]); +// c instanceof Error +``` + - *keys*: An array of key values to load. ##### `clear(key)` diff --git a/src/__tests__/dataloader.test.js b/src/__tests__/dataloader.test.js index aebf5f7..e648e15 100644 --- a/src/__tests__/dataloader.test.js +++ b/src/__tests__/dataloader.test.js @@ -62,6 +62,20 @@ describe('Primary API', () => { expect(empty).toEqual([]); }); + it('supports loading multiple keys in one call with errors', async () => { + const identityLoader = new DataLoader(keys => + Promise.resolve( + keys.map(key => (key === 'bad' ? new Error('Bad Key') : key)) + ) + ); + + const promiseAll = identityLoader.loadMany([ 'a', 'b', 'bad' ]); + expect(promiseAll).toBeInstanceOf(Promise); + + const values = await promiseAll; + expect(values).toEqual([ 'a', 'b', new Error('Bad Key') ]); + }); + it('batches multiple requests', async () => { const [ identityLoader, loadCalls ] = idLoader(); diff --git a/src/index.d.ts b/src/index.d.ts index d693354..53ca256 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -37,7 +37,7 @@ declare class DataLoader { * ]); * */ - loadMany(keys: ArrayLike): Promise; + loadMany(keys: ArrayLike): Promise>; /** * Clears the value at `key` from the cache, if it exists. Returns itself for diff --git a/src/index.js b/src/index.js index f109d48..c4b9a71 100644 --- a/src/index.js +++ b/src/index.js @@ -120,15 +120,22 @@ class DataLoader { * * var [ a, b ] = await myLoader.loadMany([ 'a', 'b' ]); * - * This is equivalent to the more verbose: + * This is similar to the more verbose: * * var [ a, b ] = await Promise.all([ * myLoader.load('a'), * myLoader.load('b') * ]); * + * However it is different in the case where any load fails. Where + * Promise.all() would reject, loadMany() always resolves, however each result + * is either a value or an Error instance. + * + * var [ a, b, c ] = await myLoader.loadMany([ 'a', 'b', 'badkey' ]); + * // c instanceof Error + * */ - loadMany(keys: $ReadOnlyArray): Promise> { + loadMany(keys: $ReadOnlyArray): Promise> { if (!isArrayLike(keys)) { throw new TypeError( 'The loader.loadMany() function must be called with Array ' + @@ -138,7 +145,7 @@ class DataLoader { // Support ArrayLike by using only minimal property access const loadPromises = []; for (let i = 0; i < keys.length; i++) { - loadPromises.push(this.load(keys[i])); + loadPromises.push(this.load(keys[i]).catch(error => error)); } return Promise.all(loadPromises); }