taxonium-component
Version:
React component for exploring large phylogenetic trees in the browser
151 lines (150 loc) • 4.74 kB
JavaScript
class h {
}
class d {
constructor() {
this.signals = /* @__PURE__ */ new Set(), this.abortController = new AbortController();
}
/**
* @param {AbortSignal} [signal] optional AbortSignal to add. if falsy,
* will be treated as a null-signal, and this abortcontroller will no
* longer be abortable.
*/
//@ts-ignore
addSignal(t = new h()) {
if (this.signal.aborted)
throw new Error("cannot add a signal, already aborted!");
this.signals.add(t), t.aborted ? this.handleAborted(t) : typeof t.addEventListener == "function" && t.addEventListener("abort", () => {
this.handleAborted(t);
});
}
handleAborted(t) {
this.signals.delete(t), this.signals.size === 0 && this.abortController.abort();
}
get signal() {
return this.abortController.signal;
}
abort() {
this.abortController.abort();
}
}
class b {
constructor() {
this.callbacks = /* @__PURE__ */ new Set();
}
addCallback(t = () => {
}) {
this.callbacks.add(t), this.currentMessage && t(this.currentMessage);
}
callback(t) {
this.currentMessage = t;
for (const e of this.callbacks)
e(t);
}
}
class c {
constructor({ fill: t, cache: e }) {
if (typeof t != "function")
throw new TypeError("must pass a fill function");
if (typeof e != "object")
throw new TypeError("must pass a cache object");
if (typeof e.get != "function" || typeof e.set != "function" || typeof e.delete != "function")
throw new TypeError("cache must implement get(key), set(key, val), and and delete(key)");
this.cache = e, this.fillCallback = t;
}
static isAbortException(t) {
return (
// DOMException
t.name === "AbortError" || // standard-ish non-DOM abort exception
//@ts-ignore
t.code === "ERR_ABORTED" || // stringified DOMException
t.message === "AbortError: aborted" || // stringified standard-ish exception
t.message === "Error: aborted"
);
}
evict(t, e) {
this.cache.get(t) === e && this.cache.delete(t);
}
fill(t, e, r, s) {
const o = new d(), i = new b();
i.addCallback(s);
const a = {
aborter: o,
promise: this.fillCallback(e, o.signal, (n) => {
i.callback(n);
}),
settled: !1,
statusReporter: i,
get aborted() {
return this.aborter.signal.aborted;
}
};
a.aborter.addSignal(r), a.aborter.signal.addEventListener("abort", () => {
a.settled || this.evict(t, a);
}), a.promise.then(() => {
a.settled = !0;
}, () => {
a.settled = !0, this.evict(t, a);
}).catch((n) => {
throw console.error(n), n;
}), this.cache.set(t, a);
}
static checkSinglePromise(t, e) {
function r() {
if (e != null && e.aborted)
throw Object.assign(new Error("aborted"), { code: "ERR_ABORTED" });
}
return t.then((s) => (r(), s), (s) => {
throw r(), s;
});
}
has(t) {
return this.cache.has(t);
}
/**
* Callback for getting status of the pending async
*
* @callback statusCallback
* @param {any} status, current status string or message object
*/
/**
* @param {any} key cache key to use for this request
* @param {any} data data passed as the first argument to the fill callback
* @param {AbortSignal} [signal] optional AbortSignal object that aborts the request
* @param {statusCallback} a callback to get the current status of a pending async operation
*/
get(t, e, r, s) {
if (!r && e instanceof AbortSignal)
throw new TypeError("second get argument appears to be an AbortSignal, perhaps you meant to pass `null` for the fill data?");
const o = this.cache.get(t);
return o ? o.aborted && !o.settled ? (this.evict(t, o), this.get(t, e, r, s)) : o.settled ? o.promise : (o.aborter.addSignal(r), o.statusReporter.addCallback(s), c.checkSinglePromise(o.promise, r)) : (this.fill(t, e, r, s), c.checkSinglePromise(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.cache.get(t).promise,
r
));
}
/**
* delete the given entry from the cache. if it exists and its fill request has
* not yet settled, the fill will be signaled to abort.
*
* @param {any} key
*/
delete(t) {
const e = this.cache.get(t);
e && (e.settled || e.aborter.abort(), this.cache.delete(t));
}
/**
* Clear all requests from the cache. Aborts any that have not settled.
* @returns {number} count of entries deleted
*/
clear() {
const t = this.cache.keys();
let e = 0;
for (let r = t.next(); !r.done; r = t.next())
this.delete(r.value), e += 1;
return e;
}
}
export {
c as A
};
//# sourceMappingURL=AbortablePromiseCache-CcuMrnn7.js.map