"use strict";
|
|
class QueueItem {
|
constructor(onLoad, onError, dependentItem) {
|
this.onLoad = onLoad;
|
this.onError = onError;
|
this.data = null;
|
this.error = null;
|
this.dependentItem = dependentItem;
|
}
|
}
|
|
/**
|
* AsyncResourceQueue is the queue in charge of run the async scripts
|
* and notify when they finish.
|
*/
|
module.exports = class AsyncResourceQueue {
|
constructor() {
|
this.items = new Set();
|
this.dependentItems = new Set();
|
}
|
|
count() {
|
return this.items.size + this.dependentItems.size;
|
}
|
|
_notify() {
|
if (this._listener) {
|
this._listener();
|
}
|
}
|
|
_check(item) {
|
let promise;
|
|
if (item.onError && item.error) {
|
promise = item.onError(item.error);
|
} else if (item.onLoad && item.data) {
|
promise = item.onLoad(item.data);
|
}
|
|
promise
|
.then(() => {
|
this.items.delete(item);
|
this.dependentItems.delete(item);
|
|
if (this.count() === 0) {
|
this._notify();
|
}
|
});
|
}
|
|
setListener(listener) {
|
this._listener = listener;
|
}
|
|
push(request, onLoad, onError, dependentItem) {
|
const q = this;
|
|
const item = new QueueItem(onLoad, onError, dependentItem);
|
|
q.items.add(item);
|
|
return request
|
.then(data => {
|
item.data = data;
|
|
if (dependentItem && !dependentItem.finished) {
|
q.dependentItems.add(item);
|
return q.items.delete(item);
|
}
|
|
if (onLoad) {
|
return q._check(item);
|
}
|
|
q.items.delete(item);
|
|
if (q.count() === 0) {
|
q._notify();
|
}
|
|
return null;
|
})
|
.catch(err => {
|
item.error = err;
|
|
if (dependentItem && !dependentItem.finished) {
|
q.dependentItems.add(item);
|
return q.items.delete(item);
|
}
|
|
if (onError) {
|
return q._check(item);
|
}
|
|
q.items.delete(item);
|
|
if (q.count() === 0) {
|
q._notify();
|
}
|
|
return null;
|
});
|
}
|
|
notifyItem(syncItem) {
|
for (const item of this.dependentItems) {
|
if (item.dependentItem === syncItem) {
|
this._check(item);
|
}
|
}
|
}
|
};
|