Skip to content

Commit

Permalink
Support ArrayLike
Browse files Browse the repository at this point in the history
  • Loading branch information
leebyron committed Nov 13, 2019
1 parent d0374ec commit 6b965e7
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 7 deletions.
6 changes: 3 additions & 3 deletions src/index.d.ts
Expand Up @@ -37,7 +37,7 @@ declare class DataLoader<K, V, C = K> {
* ]);
*
*/
loadMany(keys: ReadonlyArray<K>): Promise<V[]>;
loadMany(keys: ArrayLike<K>): Promise<V[]>;

/**
* Clears the value at `key` from the cache, if it exists. Returns itself for
Expand Down Expand Up @@ -70,8 +70,8 @@ declare namespace DataLoader {

// A Function, which when given an Array of keys, returns a Promise of an Array
// of values or Errors.
export type BatchLoadFn<K, V> =
(keys: ReadonlyArray<K>) => PromiseLike<ReadonlyArray<V | Error>>;
export type BatchLoadFn<K, V> =
(keys: ArrayLike<K>) => PromiseLike<ArrayLike<V | Error>>;

// Optionally turn off batching or caching or provide a cache key function or a
// custom cache instance.
Expand Down
24 changes: 20 additions & 4 deletions src/index.js
Expand Up @@ -129,13 +129,18 @@ class DataLoader<K, V, C = K> {
*
*/
loadMany(keys: $ReadOnlyArray<K>): Promise<Array<V>> {
if (!Array.isArray(keys)) {
if (!isArrayLike(keys)) {
throw new TypeError(
'The loader.loadMany() function must be called with Array<key> ' +
`but got: ${keys}.`
`but got: ${(keys: any)}.`
);
}
return Promise.all(keys.map(key => this.load(key)));
// Support ArrayLike by using only minimal property access
const loadPromises = [];
for (let i = 0; i < keys.length; i++) {
loadPromises.push(this.load(keys[i]));
}
return Promise.all(loadPromises);
}

/**
Expand Down Expand Up @@ -266,7 +271,7 @@ function dispatchQueueBatch<K, V>(
batchPromise.then(values => {

// Assert the expected resolution from batchLoadFn.
if (!Array.isArray(values)) {
if (!isArrayLike(values)) {
throw new TypeError(
'DataLoader must be constructed with a function which accepts ' +
'Array<key> and returns Promise<Array<value>>, but the function did ' +
Expand Down Expand Up @@ -345,4 +350,15 @@ type LoaderQueue<K, V> = Array<{
reject: (error: Error) => void;
}>;

// Private
function isArrayLike(x: mixed): boolean {
return (
typeof x === 'object' &&
x !== null &&
typeof x.length === 'number' &&
(x.length === 0 ||
(x.length > 0 && Object.prototype.hasOwnProperty.call(x, x.length - 1)))
);
}

module.exports = DataLoader;

0 comments on commit 6b965e7

Please sign in to comment.