promise缓存代理通过缓存promise实例而非返回值,实现相同参数请求的自动去重与并发共享;以序列化参数为key,支持ttl、强制刷新及错误策略等进阶控制。

用 Promise 实现异步任务结果的缓存代理,核心是:**避免重复发起相同请求,把已 resolve 的 Promise 缓存起来,后续相同请求直接返回该 Promise**。注意不是缓存值本身,而是缓存 Promise 实例——这样能自然处理并发请求(多个同时调用会共享同一个 pending 状态,只触发一次真实异步操作)。
缓存策略:以参数为 key 存储 Promise
把异步函数的参数序列化成唯一字符串(如 JSON.stringify(args)),作为缓存 map 的 key;value 是正在执行或已完成的 Promise。只要参数相同,就复用同一个 Promise 实例。
- 适合 GET 类幂等请求(如 fetchUser(id)、loadConfig())
- 不适用于带副作用或参数含函数/日期/undefined 的场景(需定制 key 生成逻辑)
- 简单场景可用 Map 或 plain object,长期运行建议加 TTL 或 LRU 清理机制
基础实现:一个通用的 promiseCache 包装器
下面是一个轻量、可复用的封装函数:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function promiseCache(fn, getKey = JSON.stringify) {
const cache = new Map();
return function(...args) {
const key = getKey(args);
if (cache.has(key)) {
return cache.get(key);
}
const promise = fn.apply(this, args).finally(() => {
// 可选:失败后不清除缓存,下次仍重试;如需失败即丢弃,把 .finally 改成 .catch(() => cache.delete(key))
});
cache.set(key, promise);
return promise;
};
}
使用示例:
const fetchUser = promiseCache(async (id) => {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error('User not found');
return res.json();
});
// 两次调用同一 id,只发一次请求
fetchUser(123).then(console.log); // 触发请求
fetchUser(123).then(console.log); // 直接复用上一个 Promise
进阶控制:支持过期、强制刷新与清除
实际项目中常需要更精细的控制:
- 带 TTL 过期:用 setTimeout 在 resolve 后延迟删除缓存;或在每次 get 前检查时间戳
- 强制刷新:给函数加一个 options 参数(如 { force: true }),绕过缓存直接执行
- 手动清除:暴露 clear(key?) 方法,方便测试或数据变更时更新缓存
- 错误缓存策略:默认不缓存 reject,如需缓存失败状态(比如防抖频繁报错),可在 catch 中 set 并加标记
注意事项:Promise 缓存 ≠ 值缓存
务必理解:你缓存的是 Promise 对象,不是最终值。这意味着:
- 并发请求天然“自动去重”——多个 await 同一个 Promise 不会重复执行
- 不能对缓存的 Promise 做 .then 链式修改(会改变原 Promise 状态),应始终基于原始调用封装
- 如果原始 Promise 被 cancel(如 AbortController),需额外处理取消逻辑,原生 Promise 不支持取消,需配合 signal 或封装成 cancellable Promise
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










