极简HTTP缓存类封装

极简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;
    }
}

核心特性说明

这个简化版本保留了最重要的三个功能:

  1. getOrSet(key, fetcher, ttl) - 核心的缓存获取/设置方法,自动处理缓存逻辑
  2. delete(key) - 删除特定缓存
  3. clear() - 清空所有缓存

自动防重复请求机制

当多个相同请求同时发生时,该类会确保:

  • 只有第一个请求实际发送到服务器
  • 后续相同请求共享同一个Promise结果
  • 避免重复的HTTP请求,减少服务器压力

缓存过期处理

  • 自动检查缓存有效期
  • 过期缓存自动删除
  • 支持自定义TTL(生存时间)
相关推荐
一拳一个娘娘腔24 分钟前
CVE-2026-43284 — Dirty Frag 深度拆解:当零拷贝遇上原地解密,页缓存成了攻击者的画板
linux·缓存
lx1885486989627 分钟前
Redis大Key阻塞:单线程CPU100%的致命陷阱
数据库·redis·缓存
IT策士30 分钟前
Redis 从入门到精通:位图、HyperLogLog、GEO
数据库·redis·缓存
布局呆星1 小时前
Spring Boot + Redis 缓存实战:@Cacheable、序列化踩坑、缓存一致性,一次讲透
spring boot·redis·缓存
努力成为AK大王2 小时前
计算机底层核心原理:CPU、总线、缓存与内存深度解析
缓存·内存·cpu
闪电悠米2 小时前
黑马点评-Redis 消息队列-04_stream_seckill_order
数据库·redis·分布式·缓存·oracle·junit·lua
通信侠3 小时前
android相机热启动缓存帧解决方案(任务快照)
android·缓存·blur·tasksnapshot·mtkcam
Albert Edison18 小时前
【Redis】Centos7.9 安装 Redis 5 教程
数据库·redis·缓存
Steadfast_GG18 小时前
Redis中的通用命令
redis·缓存
颜笑晏晏1 天前
长输入短输出场景下的 SGLang 推理性能实测前缀缓存、PD 分离配比与参数调优
缓存·推理优化·sglang·ai infra·pd分离