I have the following class that I'm using to route all my API requests through
class PromiseBroker {
#promises = {};
#overlayEle = document.getElementById('loading-overlay');
constructor(){
}
get promises(){
return this.#promises;
}
setPromise(key, value){
this.promises[key] = value;
this.#overlayEle.classList.remove('d-none');
Promise.allSettled(Object.values(this.promises)).then(results => {
this.#overlayEle.classList.add('d-none')
});
}
}
The purpose of this class is to dismiss the loading overlay once all API requests are finished. I don't know how many requests will be made ahead of time. The issue I'm having is that as promises are added, it will be dismissed prematurely. Here is what I'm referring to:
I would want to dismiss only when all promises (including ones that have been added since the allSettled
call) have been resolved. The issue, I'm assuming, is that the state changes while awaiting the promises to settle. I don't know if there is a way to cancel or overwrite the allSettled
to only use the most recent call.
Don't use allSettled
at all. Watch the completion of each individual promise only once, and keep a collection of (keys for) promises that are pending:
const defaultUpdate = activeCount => {
const overlay = document.getElementById('loading-overlay');.
overlay.classList.toggle('d-none', activeCount == 0);
};
class PromiseBroker {
#promises = {};
#active = new Set();
#update;
constructor(update = defaultUpdate) {
this.#update = update;
}
get promises(){
return this.#promises;
}
get activeCount() {
return this.#active.size;
}
setPromise(key, value) {
this.promises[key] = value;
this.#active.add(key);
this.#update(this.activeCount);
const done = () => {
this.#active.delete(key);
this.#update(this.activeCount);
};
Promise.resolve(value).then(done, done);
}
}