极简HTTP缓存类
javascript
/**
* 极简HTTP缓存管理类
* 支持缓存设置、获取、删除和防重复请求
*/
class SimpleHttpCache {
constructor() {
this.cache = new Map();
this.pendingRequests = new Map();
}
/**
* 核心方法:获取或设置缓存(支持防重复请求)
* @param {string} key - 缓存键
* @param {Function} fetcher - 数据获取函数,需返回Promise
* @param {number} ttl - 缓存时间(毫秒),默认5分钟
* @returns {Promise} 缓存数据或请求结果
*/
async getOrSet(key, fetcher, ttl = 300000) {
// 1. 检查现有缓存
const cached = this.cache.get(key);
if (cached && Date.now() < cached.expiry) {
return cached.value;
}
// 2. 防重复请求:相同请求只发送一次
if (this.pendingRequests.has(key)) {
return this.pendingRequests.get(key);
}
try {
// 3. 创建请求Promise并标记为pending
const requestPromise = fetcher();
this.pendingRequests.set(key, requestPromise);
// 4. 执行请求并缓存结果
const result = await requestPromise;
this.cache.set(key, {
value: result,
expiry: Date.now() + ttl
});
return result;
} finally {
// 5. 清理pending状态
this.pendingRequests.delete(key);
}
}
/**
* 删除指定缓存
* @param {string} key - 缓存键
*/
delete(key) {
this.cache.delete(key);
}
/**
* 清空所有缓存
*/
clear() {
this.cache.clear();
this.pendingRequests.clear();
}
}
使用示例
1. 基础使用
javascript
// 创建缓存实例
const httpCache = new SimpleHttpCache();
// 基本缓存使用
async function getUserData(userId) {
return httpCache.getOrSet(
`user:${userId}`,
() => fetch(`/api/users/${userId}`).then(r => r.json()),
60000 // 缓存1分钟
);
}
2. 防重复请求示例
javascript
// 模拟API请求
async function fetchData() {
console.log('实际发送请求...');
return new Promise(resolve => {
setTimeout(() => resolve({ data: '响应内容' }), 1000);
});
}
// 测试防重复请求
async function testDeduplication() {
const cache = new SimpleHttpCache();
// 同时发起多个相同请求
const promises = [
cache.getOrSet('test-key', fetchData),
cache.getOrSet('test-key', fetchData),
cache.getOrSet('test-key', fetchData)
];
const results = await Promise.all(promises);
console.log('所有请求完成,实际只发送了一次HTTP请求');
}
3. 实际HTTP请求场景
javascript
// 封装HTTP服务
class ApiService {
constructor() {
this.cache = new SimpleHttpCache();
}
async get(url, options = {}) {
const { ttl = 300000, ...fetchOptions } = options;
return this.cache.getOrSet(
`get:${url}:${JSON.stringify(fetchOptions)}`,
() => fetch(url, { method: 'GET', ...fetchOptions })
.then(response => {
if (!response.ok) throw new Error('请求失败');
return response.json();
}),
ttl
);
}
}
// 使用示例
const api = new ApiService();
// 自动缓存的GET请求
async function loadWidgetData(formId, fieldCode) {
try {
return await api.get(
`/api/widget/${formId}/${fieldCode}`,
{ ttl: 120000 } // 缓存2分钟
);
} catch (error) {
// 错误时自动清除相关缓存
api.cache.delete(`get:/api/widget/${formId}/${fieldCode}`);
throw error;
}
}
核心特性说明
这个简化版本保留了最重要的三个功能:
getOrSet(key, fetcher, ttl)- 核心的缓存获取/设置方法,自动处理缓存逻辑delete(key)- 删除特定缓存clear()- 清空所有缓存
自动防重复请求机制
当多个相同请求同时发生时,该类会确保:
- 只有第一个请求实际发送到服务器
- 后续相同请求共享同一个Promise结果
- 避免重复的HTTP请求,减少服务器压力
缓存过期处理
- 自动检查缓存有效期
- 过期缓存自动删除
- 支持自定义TTL(生存时间)