You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JavaScript fetch在客户端实现API请求临时缓存

原有代码的问题

你写的实现达不到自定义时长临时缓存的效果,核心缺陷有三个:

  • 用全局变量存缓存配置和定时器,并发请求时会互相覆盖状态。比如同时发起一个开缓存、一个不开缓存的请求,后执行的请求会直接改掉全局的cache值,导致配置完全错乱。
  • fetch自带的cache: "force-cache"走的是浏览器标准HTTP缓存逻辑,缓存存多久完全看服务端返回的Cache-Control响应头,客户端没法自己定2秒这种短有效期。
  • 全局定时器只要有新请求进来就会被重置,根本做不到按单个请求维度计算过期时间。
可落地的客户端缓存实现

要实现完全由客户端控制有效期的临时缓存,最可靠的方式是自己在fetch外层加一层内存缓存逻辑,不依赖浏览器默认缓存规则,缓存键、有效期完全可控,特别适合大体积JSON响应的短时间缓存场景。

核心逻辑:

  • 用Map做缓存存储,每条缓存记录保存响应副本和过期时间戳
  • 缓存键由请求方法、路径、参数共同生成,避免不同参数的请求命中错误缓存
  • 请求前先查缓存,未过期直接返回缓存内容,过期则发起真实请求,请求成功后把响应副本写入缓存
  • 注意要缓存Response的克隆对象,因为fetch返回的Response是流对象,读取一次就会消耗,直接存原对象会导致缓存命中后拿不到数据

完整实现代码:

// 缓存存储,key为请求唯一标识,value为 { data: 响应克隆对象, expireTime: 过期时间戳 }
const requestCache = new Map();

/**
 * 封装fetch请求,支持客户端自定义时长缓存
 * @param {string} path 请求路径
 * @param {string} method 请求方法,默认GET
 * @param {object} params 请求参数,GET请求自动拼为查询参数,其他方法作为请求体
 * @param {boolean} allowCache 是否开启临时缓存,默认false
 * @param {number} cacheTTL 缓存有效期,单位毫秒,默认2000毫秒
 * @returns {Promise<Response>} fetch响应对象
 */
async function request(path, method = "GET", params = {}, allowCache = false, cacheTTL = 2000) {
    // 构造唯一缓存key
    const cacheKey = `${method.toUpperCase()}_${path}_${JSON.stringify(params)}`;

    // 开启缓存的场景先查缓存
    if (allowCache) {
        const cachedItem = requestCache.get(cacheKey);
        // 缓存存在且未过期,直接返回缓存的响应克隆
        if (cachedItem && Date.now() < cachedItem.expireTime) {
            return cachedItem.data.clone();
        }
        // 缓存过期就删掉旧记录
        requestCache.delete(cacheKey);
    }

    // 构造fetch配置
    const options = {
        method: method.toUpperCase(),
        headers: {
            "Content-Type": "application/json"
        }
    };

    // 处理参数:GET拼查询串,其他方法序列化请求体
    let requestUrl = path;
    if (method.toUpperCase() === "GET") {
        const searchParams = new URLSearchParams(params);
        requestUrl = `${path}?${searchParams.toString()}`;
    } else {
        options.body = JSON.stringify(params);
    }

    // 发起真实请求
    const response = await fetch(requestUrl, options);

    // 开启缓存的场景,写入缓存(存克隆对象,避免原响应被读取后缓存失效)
    if (allowCache && response.ok) {
        requestCache.set(cacheKey, {
            data: response.clone(),
            expireTime: Date.now() + cacheTTL
        });

        // 到期自动清理过期缓存,避免内存无限增长
        setTimeout(() => {
            const currentItem = requestCache.get(cacheKey);
            if (currentItem && Date.now() >= currentItem.expireTime) {
                requestCache.delete(cacheKey);
            }
        }, cacheTTL);
    }

    return response;
}

使用说明

  • 调用时传allowCache: true即可开启默认2秒的缓存,需要自定义时长可以传cacheTTL参数,单位为毫秒,比如要缓存1分钟就传60000
  • 默认GET请求会把参数自动拼接到URL查询串,非GET请求会把参数序列化为JSON请求体
  • 缓存默认存在内存里,页面刷新后会清空,如果需要持久化缓存,可以把存储层换成Cache Storage,核心逻辑不用改
  • 非GET请求开启缓存前要确认接口是幂等的,不要把提交、删除类的写操作接口缓存,避免业务异常

内容的提问来源于stack exchange,提问作者user19249111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:21:19