prostgles-client
Version:
Reactive client for Postgres
78 lines (77 loc) • 2.89 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useAsyncEffectQueue = void 0;
const useEffectDeep_1 = require("./useEffectDeep");
const reactImports_1 = require("../hooks/reactImports");
const { useRef } = reactImports_1.reactImports;
/**
* Debounce with execute first
* Used to ensure subscriptions are always cleaned up
*/
const useAsyncEffectQueue = (effect, deps, debounce) => {
const idRef = useRef(0);
const isMounted = useRef(true);
const newEffect = useRef();
const activeEffect = useRef();
const onRender = async () => {
var _a, _b;
/**
* Await and cleanup previous effect
* */
if (((_a = activeEffect.current) === null || _a === void 0 ? void 0 : _a.state) === "resolved") {
const { cleanup, effect, id } = activeEffect.current;
activeEffect.current = { id, state: "cleaning", effect };
await cleanup().catch(console.error);
activeEffect.current = { id, state: "cleaned", effect };
}
/**
* Start new effect
*/
if (newEffect.current &&
(!activeEffect.current || activeEffect.current.state === "cleaned") &&
((_b = activeEffect.current) === null || _b === void 0 ? void 0 : _b.id) !== newEffect.current.id) {
const currentEffect = newEffect.current;
const { effect, id } = currentEffect;
activeEffect.current = { id, state: "resolving", effect };
const cleanup = await effect()
.then((run) => {
/* Wrapped in a promise to ensure cleanup is awaited */
return async () => {
await (run === null || run === void 0 ? void 0 : run());
};
})
.catch((e) => {
console.error(e);
return async () => { };
});
activeEffect.current = { id, state: "resolved", effect, cleanup };
if (!isMounted.current ||
currentEffect !== newEffect.current ||
activeEffect.current.id !== newEffect.current.id) {
onRender();
}
}
};
const timerRef = useRef(null);
const scheduleRender = () => {
if (!debounce) {
onRender();
return;
}
if (timerRef.current)
clearTimeout(timerRef.current);
timerRef.current = setTimeout(() => {
onRender();
}, debounce);
};
(0, useEffectDeep_1.useEffectDeep)(() => {
isMounted.current = true;
newEffect.current = { effect, deps, id: ++idRef.current };
scheduleRender();
return () => {
isMounted.current = false;
scheduleRender();
};
}, deps);
};
exports.useAsyncEffectQueue = useAsyncEffectQueue;