perf(web): 优化大数据量页面切换与聚合性能

This commit is contained in:
Script Generator
2026-07-03 09:43:36 +08:00
parent 554ab520d1
commit a509bb4922
32 changed files with 1087 additions and 360 deletions

View File

@@ -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 &&