Progress on priority loading

This commit is contained in:
Jordan Eldredge 2018-08-09 22:50:58 -07:00
parent 7da7622996
commit 96d1537b80
3 changed files with 61 additions and 15 deletions

View file

@ -16,3 +16,8 @@
box-shadow: 0px 0px 15px 5px rgba(46, 46, 139, 0.75);
*/
}
.priority {
position: absolute;
background: white;
}

View file

@ -15,26 +15,34 @@ const OVERSCAN_ROWS_TRAILING = 4;
class Skin extends React.Component {
constructor(props) {
super(props);
this.state = { loaded: false, load: false };
this.state = { loaded: false, load: false, enqueuedAs: null };
this._controller = new window.AbortController();
this._handleLoad = this._handleLoad.bind(this);
}
_getPriority() {
return this.props.isOverscan ? 1 : 0;
}
componentDidUpdate(prevProps) {
if (prevProps.isOverscan != this.props.isOverscan) {
// TODO: Update priority
if (this._queued && !(this.state.load || this.state.loaded)) {
this._queued.changePriority(this._getPriority());
if (this.state.enqueuedAs !== this._getPriority()) {
this.setState({ enqueuedAs: this._getPriority() });
}
}
}
componentDidMount() {
this._dequeue = this.props.queue.enqueue(() => {
this._queued = this.props.queue.enqueue(() => {
const signal = this._controller.signal;
return fetch(this.props.src, { signal, mode: "no-cors" })
.then(() => {
this.setState({ load: true });
})
.catch(e => {});
}, this.props.isOverscan ? 1 : 0);
}, this._getPriority());
this.setState({ enqueuedAs: this._getPriority() });
}
_handleLoad() {
@ -45,8 +53,9 @@ class Skin extends React.Component {
if (!this.state.loaded) {
this._controller.abort();
}
if (this._dequeue != null) {
this._dequeue();
if (this._queued != null) {
this._queued.dispose();
this._queued = null;
}
}
@ -56,8 +65,8 @@ class Skin extends React.Component {
className={"skin"}
style={{
position: "absolute",
top: 0,
left: 0,
// Ideally the final backgroundColor would be black
// But that makes our opacitly transition kinda funky
backgroundColor: this.props.color,
width: this.props.width,
height: this.props.height,
@ -65,6 +74,10 @@ class Skin extends React.Component {
left: this.props.left
}}
>
<div className="priority">
{this.state.enqueuedAs} -{" "}
{this.state.load && !this.state.loaded ? "loading..." : ""}
</div>
<a href={this.props.href} target="_blank">
{this.state.load && (
<img

View file

@ -2,6 +2,7 @@ export default class LoadQueue {
constructor(size) {
this._free = size;
this._queue = new Array();
this.size = 0;
}
_remove(priority, cb) {
@ -9,28 +10,53 @@ export default class LoadQueue {
if (priorityQueue == null) {
return;
}
priorityQueue.delete(cb);
if (priorityQueue.size === 0) {
this._queue[priority] = undefined;
if (priorityQueue.has(cb)) {
this.size--;
priorityQueue.delete(cb);
if (priorityQueue.size === 0) {
// TODO: Consider splicing this out
this._queue[priority] = undefined;
}
}
}
enqueue(cb, priority) {
enqueue(cb, priority_) {
let priority = priority_;
if (this._queue[priority] == null) {
this._queue[priority] = new Set();
}
this._queue[priority].add(cb);
this.size++;
this._run();
return () => {
this._remove(priority, cb);
const resp = {
dispose: () => {
this._remove(priority, cb);
},
changePriority: newPriority => {
if (newPriority == priority) {
return resp;
}
this._remove(priority, cb);
this.enqueue(cb, newPriority);
priority = newPriority;
}
};
return resp;
}
_state() {
return this._queue.map((v, i) => v && `${i} -> ${v.size}`).filter(Boolean);
}
_run() {
if (this._free === 0) {
return;
}
// This should skip over sparse portions of the array.
// FALSE
const priority = this._queue.findIndex(value => Boolean(value));
if (priority === -1) {
// The queue is empty
@ -41,8 +67,10 @@ export default class LoadQueue {
const values = set.values();
const cb = values.next().value;
console.log("Started priority", priority, "Queue size", this._state());
cb().finally(() => {
this._free++;
console.log("Finished priority", priority, "Queue size", this._state());
this._run();
});