极简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(生存时间)
相关推荐
知我Deja_Vu3 天前
redisCommonHelper.generateCode(“GROUP“),Redis 生成码方法
数据库·redis·缓存
没有bug.的程序员3 天前
电商秒杀系统深度进阶:高并发流量建模、库存零超卖内核与 Redis+MQ 闭环
数据库·redis·缓存·高并发·电商秒杀·流量建模·库存零超卖
troublea3 天前
ThinkPHP3.x高效学习指南
mysql·nginx·缓存
troublea3 天前
ThinkPHP6快速入门指南
数据库·mysql·缓存
Emotional。3 天前
AI Agent 性能优化和成本控制
人工智能·深度学习·机器学习·缓存·性能优化
jnrjian3 天前
Oracle 共享池 库缓存下的 Library Cache Lock
数据库·缓存·oracle
Anastasiozzzz4 天前
阿亮随手记:MySQL移除查询缓存、子查询优化深分页、自增主键溢出、索引失效
数据库·mysql·缓存
難釋懷4 天前
Redis消息队列-基于Stream的消息队列-消费者组
数据库·redis·缓存
難釋懷4 天前
Redis消息队列-基于Stream的消息队列
数据库·redis·缓存
troublea4 天前
Laravel 8.x新特性全解析
数据库·mysql·缓存