/** * 简单 TTL 内存缓存。 * 命中:直接返回缓存值;过期或未命中:运行 loader、存入缓存。 * 同一 key 并发请求只会触发一次 loader(共享 in-flight Promise)。 */ interface Entry { value: T; expiresAt: number; } const TTL_MS = 60 * 1000; const cache = new Map>(); const inflight = new Map>(); export async function cached(key: string, loader: () => Promise): Promise { const now = Date.now(); const hit = cache.get(key); if (hit && hit.expiresAt > now) { return hit.value as T; } // 同一 key 并发只跑一次 loader const ongoing = inflight.get(key) as Promise | undefined; if (ongoing) return ongoing; const p = loader() .then(value => { cache.set(key, { value, expiresAt: Date.now() + TTL_MS }); return value; }) .finally(() => { inflight.delete(key); }); inflight.set(key, p as Promise); return p; } /** 仅用于测试或调试:清空所有缓存 */ export function _clearEnergyCache() { cache.clear(); inflight.clear(); }