| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- import { useEffect, useRef, useState } from "react";
- import { getApiCache, getGlobalStorage } from "./storage";
- interface UseSWCOPtions<T> {
- onError?: (e: unknown) => void;
- onLoad?: (data: T) => void;
- cacheOnly?: boolean;
- cacheTimeout?: number;
- }
- // 该hook用于在组件中通过key和异步action获取数据,并自动处理加载、错误和数据状态
- export function useSWC<T>(key: string, action: () => Promise<T>, options?: UseSWCOPtions<T>) {
- const optionsRef = useRef(options);
- optionsRef.current = options;
-
- const [data, setData] = useState<T | null | undefined>(() => {
- try {
- const data = JSON.parse(getApiCache().getString(`$swc-${key}`) || "null") as T;
- if (!data) {
- return undefined;
- }
- let ttl = optionsRef.current?.cacheTimeout || MAX_CACHE_TIME;
- // @ts-ignore
- let cacheTime = data.$__cacheTime;
- if (Date.now() - cacheTime > ttl * 1000) {
- return undefined;
- }
- return data;
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- } catch (_) {
- return undefined;
- }
- });
- const [loading, setLoading] = useState<boolean>(true);
- const [error, setError] = useState<any>(null);
- const actionRef = useRef(action);
- actionRef.current = action;
- const dataRef = useRef(data);
- dataRef.current = data;
- const keyRef = useRef(key);
- useEffect(() => {
- let isMounted = true;
- if (dataRef.current && optionsRef.current?.cacheOnly) {
- return;
- }
- setLoading(true);
- setError(null);
-
- const options = optionsRef.current;
- const key = keyRef.current;
- actionRef.current()
- .then((result) => {
- // @ts-ignore
- result.$__cacheTime = Date.now();
- result && getApiCache().set(`$swc-${key}`, JSON.stringify(result));
- if (isMounted) {
- options?.onLoad?.(result);
- setData(result);
- setLoading(false);
- }
- })
- .catch((err) => {
- if (isMounted) {
- options?.onError?.(err);
- setError(err);
- setLoading(false);
- }
- });
- return () => {
- isMounted = false;
- };
-
- }, []);
- return { data, loading, error };
- }
- export const MAX_CACHE_TIME = 99999999999999;
- let lastClearTime = parseInt(getGlobalStorage().getString("last_clear_time") || "0");
- const clearTimeout = 86400 * 3 * 1000;
- // 开启一直 30 分钏的定时器,用于清理缓存
- setInterval(() => {
-
- let now = Date.now();
- if (now - lastClearTime < clearTimeout) {
- lastClearTime = now;
- const globalStorage = getGlobalStorage();
- const caches = getApiCache();
- caches.getAllKeys().forEach(key => {
- try {
- let {$__cacheTime} = JSON.parse(caches.getString(key) || `{"$__cacheTime": ${MAX_CACHE_TIME}}`);
- if (now - $__cacheTime > clearTimeout) {
- caches.remove(key);
- }
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- } catch (_e) {
- }
- });
- globalStorage.set("last_clear_time", now+"");
- }
- }, 60 * 15 * 1000);
|