55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
import { onMounted, onServerPrefetch, type ShallowRef, shallowRef } from "vue";
|
|
import useDjSSRContext from "@/useDjSSRContext.ts";
|
|
|
|
declare global {
|
|
var appstate: Partial<Record<string, unknown>>;
|
|
}
|
|
|
|
export default function useAsyncState<T>(
|
|
key: string,
|
|
getter: (context: { hostUrl: string }) => Promise<T | null>,
|
|
options?: { suspensible: boolean },
|
|
): { result: ShallowRef<T | null>; done: Promise<void> } {
|
|
const ssrContext = useDjSSRContext();
|
|
const isClient = typeof ssrContext === "undefined";
|
|
|
|
const registry = ssrContext?.registry ?? globalThis?.appstate;
|
|
|
|
const hostUrl = isClient ? globalThis.location.origin : "http://localhost:8080";
|
|
|
|
const state = shallowRef<T | null>(null);
|
|
|
|
let resolve = () => {};
|
|
const promise = new Promise<void>((res) => {
|
|
resolve = res;
|
|
});
|
|
|
|
if (key in registry) {
|
|
state.value = registry[key] as T;
|
|
delete registry[key];
|
|
resolve();
|
|
} else {
|
|
if (!isClient) {
|
|
resolve();
|
|
}
|
|
onServerPrefetch(async () => {
|
|
const result = await getter({ hostUrl });
|
|
registry[key] = result;
|
|
state.value = result;
|
|
});
|
|
if (options?.suspensible ?? true) {
|
|
getter({ hostUrl }).then((result) => {
|
|
state.value = result;
|
|
resolve();
|
|
}).catch(resolve);
|
|
} else {
|
|
onMounted(async () => {
|
|
state.value = await getter({ hostUrl });
|
|
resolve();
|
|
});
|
|
}
|
|
}
|
|
|
|
return { result: state, done: promise };
|
|
}
|