UNPKG

prostgles-client

Version:

Reactive client for Postgres

78 lines (77 loc) 2.89 kB
"use strict"; 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;