通过维护一个全局的 pendingpromises 映射表,在发起异步请求前检查是否存在相同条件的 promise。如果存在则直接复用该 promise 实例,从而合并调用并去重;如果不存在则创建新的 promise,将其存入映射表并在其 then 或 catch 回调中清理缓存,确保后续相同请求能触发新任务。

如何根据唯一键识别重复请求
利用对象作为哈希表的核心在于构建稳定的唯一标识符(Key)。对于网络请求,通常使用 URL 加上查询参数作为 Key。实现时,需要遍历当前所有待处理的 Promise,判断传入的参数是否与已有 Key 匹配。若匹配成功,直接返回对应的 Promise 对象,避免重复执行底层逻辑。

const pendingRequests = new Map();
function deduplicatedFetch(url) {
if (pendingRequests.has(url)) {
return pendingRequests.get(url);
}
const promise = fetch(url)
.then(res => res.json())
.finally(() => {
pendingRequests.delete(url);
});
pendingRequests.set(url, promise);
return promise;
}
上述代码展示了基于 Map 的基础去重逻辑。当多个组件同时调用 deduplicatedFetch('/api/data') 时,只有第一个调用会真正发起网络请求,其余调用均共享同一个 Promise 结果。这种机制有效减少了服务器负载和浏览器并发连接数。
如何处理不同参数的并行请求
当请求参数发生变化时,系统应视为独立任务处理。例如,分页请求中页码不同即代表数据不同,不应被去重。此时需将参数序列化后生成新的 Key。同时,需确保旧任务的清理不会干扰新任务的创建。通过 finally 块保证无论请求成功或失败,缓存都会被正确移除,维持状态一致性。

function getDeduplicatedData(params) {
const key = JSON.stringify(params);
if (pendingRequests.has(key)) {
return pendingRequests.get(key);
}
const promise = fetchData(params)
.then(data => data)
.catch(err => { throw err; })
.finally(() => {
pendingRequests.delete(key);
});
pendingRequests.set(key, promise);
return promise;
}
此方案适用于动态参数场景。通过序列化参数生成唯一 Key,确保了不同配置下的请求互不干扰。开发者需注意,若参数中包含非结构化数据(如函数引用),序列化可能失效,此时建议自定义 Key 生成策略。此外,内存管理至关重要,及时清理已完成的 Promise 可防止内存泄漏。
基于程序中某个输入、条件或结果的具体问题
当请求因网络错误被拒绝时,Promise 的状态变为 rejected。此时 finally 块依然会执行,确保缓存被清除。这意味着下一次相同请求会重新发起,而不是复用失败的 Promise。这种行为符合预期,因为失败的数据不应被缓存供后续使用。若需缓存失败状态,需修改逻辑,在 catch 中保留引用而非删除。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











