react-cache-promise
Version:
react-cache-promise
96 lines (93 loc) • 3.02 kB
JavaScript
import * as React from 'react';
const promiseCache = new Map();
const reverseCache = new Map();
function createCache(arg, promise) {
let subscriptionCache = {
subscribe,
state: null,
active: true,
};
promise.then(fulfilledValue => {
if (subscriptionCache.active) {
subscriptionCache.state = { status: "fulfilled", value: fulfilledValue };
if (subscriptionCache.listeners) {
Object.values(subscriptionCache.listeners).forEach(cb => {
React.startTransition(() => cb(fulfilledValue));
});
}
}
}, (error) => {
if (subscriptionCache.active) {
subscriptionCache.state = { status: "rejected", reason: error };
if (subscriptionCache.listeners) {
Object.values(subscriptionCache.listeners).forEach(cb => {
React.startTransition(() => cb(error));
});
}
}
});
function subscribe(cb) {
if (!subscriptionCache.index) {
subscriptionCache.index = 0;
}
if (!subscriptionCache.listeners) {
subscriptionCache.listeners = [];
}
let id = ++subscriptionCache.index;
subscriptionCache.listeners[id] = cb;
return () => {
delete subscriptionCache.listeners[id];
};
}
return subscriptionCache;
}
function patchQuery(fn, getCacheArg) {
function modified(...args) {
let arg = getCacheArg.apply(null, args);
let cachedPromise = promiseCache.get(arg);
if (cachedPromise) {
return cachedPromise;
}
let promise = fn.apply(null, args);
promiseCache.set(arg, promise);
reverseCache.set(promise, createCache(arg, promise));
return promise;
}
return modified;
}
function usePromise(promise) {
let subscription = reverseCache.get(promise);
let state = subscription.state;
if (state === null) {
throw promise;
}
if (state.status === "rejected") {
throw state.reason;
}
let rerender = React.useState()[1];
React.useEffect(() => subscription.subscribe(rerender), [subscription]);
return state.value;
}
function evict(arg) {
let promise = promiseCache.get(arg);
if (!promise) {
return;
}
let subscription = reverseCache.get(promise);
if (!subscription) {
return;
}
let returnValue = promiseCache.delete(arg) && reverseCache.delete(promise);
subscription.active = false;
subscription.state = null;
let listeners = subscription.listeners;
if (listeners) {
let newObject = {};
Object.values(listeners).forEach(cb => {
React.startTransition(() => cb(newObject));
});
}
return returnValue;
}
export { evict, patchQuery, usePromise };
//# sourceMappingURL=index.js.map