class ListItem {
data: any | null
dom: HTMLElement | null
tombstone: HTMLElement | null
width: number
height: number
pos: number
constructor() {
this.data = null
this.dom = null
this.tombstone = null
this.width = 0
this.height = 0
this.pos = 0
}
}
export type pListItem = Partial
export default class DataManager {
public loadedNum = 0
private fetching = false
private hasMore = true
private list: Array
constructor(
list: Array,
private fetchFn: (len: number) => Promise | boolean>,
private onFetchFinish: (list: Array, hasMore: boolean) => number
) {
this.list = list || []
}
async update(end: number): Promise {
if (!this.hasMore) {
end = Math.min(end, this.list.length)
}
// add data placeholder
if (end > this.list.length) {
const len = end - this.list.length
this.addEmptyData(len)
}
// tslint:disable-next-line: no-floating-promises
return this.checkToFetch(end)
}
add(data: Array): Array {
for (let i = 0; i < data.length; i++) {
if (!this.list[this.loadedNum]) {
this.list[this.loadedNum] = { data: data[i] }
} else {
this.list[this.loadedNum] = {
...this.list[this.loadedNum],
...{ data: data[i] },
}
}
this.loadedNum++
}
return this.list
}
addEmptyData(len: number): Array {
for (let i = 0; i < len; i++) {
this.list.push(new ListItem())
}
return this.list
}
async fetch(len: number): Promise | boolean> {
if (this.fetching) {
return []
}
this.fetching = true
const data = await this.fetchFn(len)
this.fetching = false
return data
}
async checkToFetch(end: number): Promise {
if (!this.hasMore) {
return
}
if (end <= this.loadedNum) {
return
}
const min = end - this.loadedNum
const newData = await this.fetch(min)
if (newData instanceof Array && newData.length) {
this.add(newData)
const currentEnd = this.onFetchFinish(this.list, true)
return this.checkToFetch(currentEnd)
} else if (typeof newData === 'boolean' && newData === false) {
this.hasMore = false
this.list.splice(this.loadedNum)
this.onFetchFinish(this.list, false)
}
}
getList() {
return this.list
}
resetState() {
this.loadedNum = 0
this.fetching = false
this.hasMore = true
this.list = []
}
}