const cache = new Map();
async function cachedFetch(key, loader, ttlMs) {
if (typeof key !== "string" || key.length === 0) {
throw new TypeError("key must be a non-empty string");
}
if (typeof loader !== "function") {
throw new TypeError("loader must be a function");
}
if (!Number.isFinite(ttlMs) || ttlMs < 0) {
throw new RangeError("ttlMs must be a non-negative number");
}
const now = Date.now();
const cached = cache.get(key);
if (cached) {
if (cached.expiresAt > now) {
return cached.promise;
}
cache.delete(key);
}
const promise = Promise.resolve().then(loader);
const entry = {
promise,
expiresAt: now + ttlMs,
};
cache.set(key, entry);
try {
return await promise;
} catch (error) {
if (cache.get(key) === entry) {
cache.delete(key);
}
throw error;
}
}
const cache = new Map();
async function cachedFetch(key, loader, ttlMs) {
const now = Date.now();
const cached = cache.get(key);
if (cached && (cached.pending || cached.expiresAt > now)) {
return cached.promise;
}
const entry = {
pending: true,
expiresAt: Infinity,
promise: null,
};
entry.promise = Promise.resolve()
.then(loader)
.then((value) => {
entry.pending = false;
entry.expiresAt = Date.now() + ttlMs;
return value;
})
.catch((error) => {
if (cache.get(key) === entry) {
cache.delete(key);
}
throw error;
});
cache.set(key, entry);
return entry.promise;
}