前端面试 P097:请求去重、缓存键与过期策略
Showing the original in Chinese (China)
来源:方格前端讲面试 · 如何解决页面请求接口大规模并发问题,15 分 37 秒。
去重与缓存不同
去重让同一份进行中工作共享 Promise;缓存让结束后的结果在一定条件下继续复用。合并多个业务操作为批量接口又是另一层,不能都叫“一次请求”。
function createDedupe() {
const pending = new Map();
return function request(key, task) {
if (pending.has(key)) return pending.get(key);
const promise = Promise.resolve().then(task).finally(() => {
if (pending.get(key) === promise) pending.delete(key);
});
pending.set(key, promise);
return promise;
};
}
成功或失败后都移除进行中条目,因此下一次可重新执行。拒绝不被吞掉,等待者共享同一失败结果。
key 必须覆盖结果身份
方法、URL、规范化参数、请求体、用户或租户、语言和相关权限范围都可能影响结果。不能只用路径缓存私有数据,也不能随意用 JSON.stringify 编任意对象并假定无碰撞。
共享请求的取消要设计:一个消费者取消,不应无意取消仍被其他消费者需要的底层请求,可用引用计数或区分订阅取消和任务取消。
过期与失效
TTL 是一种近似时效策略,不保证数据绝对新鲜;写入后失效、版本号、重新验证、容量限制和错误缓存要按业务决定。过期读取只清当前项,还应考虑长期不访问条目的内存上限。
浏览器 HTTP 缓存、应用内 Map、localStorage、CDN 和服务端缓存不是同一层,各有共享范围与安全语义。完整服务端状态管理见 前端面试 P091:SWR、TanStack Query 与服务端缓存。