Skip to content

Instantly share code, notes, and snippets.

@JoshMock
Created August 14, 2015 21:56
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save JoshMock/98f187c7a8bf745e4cf6 to your computer and use it in GitHub Desktop.
Save JoshMock/98f187c7a8bf745e4cf6 to your computer and use it in GitHub Desktop.
ES6 all the things
import { EventEmitter } from 'events';
export class AsyncArray extends EventEmitter {
constructor(fetch, maxSize = 1000, pageSize = 100) {
super();
this.cache = new Map();
this.requestsInProgress = new Set();
this.fetch = fetch;
this.maxSize = maxSize;
this.pageSize = pageSize;
}
get(index) {
// try to get from this.cache
if (this.cache.has(index)) {
return this.cache.get(index);
} else {
// fetch page containing requested index
let pageStart = Math.floor(index / this.pageSize) * this.pageSize;
let requestKey = `${pageStart}-${this.pageSize}`;
if (!this.requestsInProgress.has(requestKey)) {
this.requestsInProgress.add(requestKey);
this.fetch(pageStart, this.pageSize)
// cache items returned
.then(data => data.forEach((item, itemIndex) => this._cacheItem(itemIndex + pageStart, item)))
.then(() => this.emit('change'))
.always(() => this.requestsInProgress.delete(requestKey));
}
// return empty placeholder
return null;
}
}
_cacheItem(index, item) {
// add item to cache
this.cache.set(index, item);
// drop oldest data from cache as needed
if (this.cache.length > this.maxSize) {
let dropCount = this.cache.length - this.maxSize;
let itemCount = 0;
for (let cachedItem of this.cache.keys()) {
if (itemCount < dropCount) {
this.cache.delete(cachedItem);
itemCount++;
} else {
break;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment