perf(web): 优化大数据量页面切换与聚合性能
This commit is contained in:
@@ -30,6 +30,18 @@ type ServerDataConflictBody<T> = {
|
||||
};
|
||||
|
||||
const serverDataVersions = new Map<ServerDataKey, string | null>();
|
||||
const serverDataCache = new Map<ServerDataKey, {
|
||||
value: unknown | null;
|
||||
version: string | null;
|
||||
loadedAt: number;
|
||||
}>();
|
||||
const serverDataLoadPromises = new Map<ServerDataKey, Promise<unknown | null>>();
|
||||
export const SERVER_DATA_CACHE_MS = 30_000;
|
||||
|
||||
type LoadServerDataOptions = {
|
||||
force?: boolean;
|
||||
maxAgeMs?: number;
|
||||
};
|
||||
|
||||
export class ServerDataConflictError<T = unknown> extends Error {
|
||||
constructor(
|
||||
@@ -42,10 +54,36 @@ export class ServerDataConflictError<T = unknown> extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadServerData<T>(key: ServerDataKey): Promise<T | null> {
|
||||
const res = await api.get<ServerDataResponse<T>>(`/data/${key}`);
|
||||
serverDataVersions.set(key, res.version ?? null);
|
||||
return res.value;
|
||||
export async function loadServerData<T>(
|
||||
key: ServerDataKey,
|
||||
options: LoadServerDataOptions = {},
|
||||
): Promise<T | null> {
|
||||
const maxAgeMs = options.maxAgeMs ?? SERVER_DATA_CACHE_MS;
|
||||
const cached = serverDataCache.get(key);
|
||||
if (!options.force && cached && maxAgeMs > 0 && Date.now() - cached.loadedAt <= maxAgeMs) {
|
||||
return cached.value as T | null;
|
||||
}
|
||||
|
||||
const inFlight = serverDataLoadPromises.get(key);
|
||||
if (inFlight) return inFlight as Promise<T | null>;
|
||||
|
||||
const promise = api.get<ServerDataResponse<T>>(`/data/${key}`)
|
||||
.then((res) => {
|
||||
const version = res.version ?? null;
|
||||
serverDataVersions.set(key, version);
|
||||
serverDataCache.set(key, {
|
||||
value: res.value,
|
||||
version,
|
||||
loadedAt: Date.now(),
|
||||
});
|
||||
return res.value;
|
||||
})
|
||||
.finally(() => {
|
||||
serverDataLoadPromises.delete(key);
|
||||
});
|
||||
|
||||
serverDataLoadPromises.set(key, promise as Promise<unknown | null>);
|
||||
return promise;
|
||||
}
|
||||
|
||||
export async function saveServerData<T>(key: ServerDataKey, value: T): Promise<void> {
|
||||
@@ -56,7 +94,13 @@ export async function saveServerData<T>(key: ServerDataKey, value: T): Promise<v
|
||||
|
||||
try {
|
||||
const res = await api.put<ServerDataResponse<T>>(`/data/${key}`, payload);
|
||||
serverDataVersions.set(key, res.version ?? null);
|
||||
const version = res.version ?? null;
|
||||
serverDataVersions.set(key, version);
|
||||
serverDataCache.set(key, {
|
||||
value,
|
||||
version,
|
||||
loadedAt: Date.now(),
|
||||
});
|
||||
} catch (error) {
|
||||
if (
|
||||
error instanceof ApiRequestError &&
|
||||
|
||||
Reference in New Issue
Block a user