极简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(生存时间)
相关推荐
@淡 定4 小时前
Redis持久化机制
数据库·redis·缓存
2501_941148155 小时前
从边缘节点到云端协同的分布式缓存一致性实现原理实践解析与多语言代码示例分享笔记集录稿
笔记·分布式·物联网·缓存
@淡 定7 小时前
主流缓存中间件对比:Redis vs Memcached
redis·缓存·中间件
阿佳举世无双7 小时前
快速启动redis
数据库·redis·缓存
星辰_mya7 小时前
redis主从同步-概览
数据库·redis·缓存
写代码的小阿帆10 小时前
Java本地缓存技术——Guava、Caffeine
java·缓存·guava
我爱娃哈哈11 小时前
告别Redis瓶颈:Caffeine本地缓存优化实战指南
数据库·redis·缓存
机灵猫11 小时前
Redis 内部机制:持久化、内存淘汰与延迟优化
数据库·redis·缓存
快乐的划水a12 小时前
「CIC→DMA→FIFO」的完整数据流程
缓存