Skip to content

Instantly share code, notes, and snippets.

@kevincennis
Created September 14, 2018 02:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kevincennis/2377cfcb801955658848b42e118d87d3 to your computer and use it in GitHub Desktop.
Save kevincennis/2377cfcb801955658848b42e118d87d3 to your computer and use it in GitHub Desktop.
DataLoader
const nextTick = () => Promise.resolve();
class DataLoader {
constructor( batch ) {
this.batch = batch;
this.queue = [];
this.cache = new Map();
}
async load( key ) {
if ( this.cache.has( key ) ) {
return this.cache.get( key );
}
const promise = new Promise( ( resolve, reject ) => {
this.queue.push({ key, resolve, reject });
if ( this.queue.length === 1 ) {
nextTick().then( () => dispatch( this ) );
}
});
this.cache.set( key, promise );
return promise;
}
}
async function dispatch( loader ) {
const queue = loader.queue;
const cache = loader.cache;
const keys = loader.queue.map( ({ key }) => key );
loader.queue = [];
loader.cache = new Map;
try {
const values = await loader.batch( keys );
queue.forEach( ( { key, resolve }, index ) => {
resolve( values[ index ] );
});
} catch ( err ) {
queue.forEach( ({ reject }) => reject( err ) );
}
}
const data = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Tom' }
];
const loader = new DataLoader(
async keys => {
console.log('batch');
return data.filter( d => keys.includes( d.id ) );
}
);
Promise.all([
loader.load( 1 ),
loader.load( 2 ),
loader.load( 3 ),
loader.load( 3 )
]).then( console.log.bind( console ) );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment