Create a gist now

Instantly share code, notes, and snippets.

@JoshMock /async-array.js Secret
Created Aug 14, 2015

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