TypechoJoeTheme

至尊技术网

统计
登录
用户名
密码

JavaScript请求缓存实战:提升性能的五大策略

2025-09-06
/
0 评论
/
1 阅读
/
正在检测是否收录...
09/06

JavaScript请求缓存实战:提升性能的五大策略

一、理解请求缓存的本质

前端开发中,频繁的网络请求会导致性能瓶颈。我曾参与过一个电商项目,商品列表页的API请求在没有缓存策略时,平均加载时间达到3.2秒。通过实现请求缓存后,这个数字降到了1.4秒——这让我深刻认识到缓存的重要性。

请求缓存的核心思想是:当相同请求再次发生时,优先使用本地存储的响应数据。与浏览器默认缓存不同,我们需要实现的是应用层缓存控制,这给了开发者更大的灵活性。

二、基础实现方案

javascript
const cacheMap = new Map();

async function cachedFetch(url, options = {}) {
const cacheKey = ${url}_${JSON.stringify(options)};

if (cacheMap.has(cacheKey)) {
console.log('[缓存命中]', cacheKey);
return Promise.resolve(cacheMap.get(cacheKey));
}

try {
const response = await fetch(url, options);
const data = await response.json();

cacheMap.set(cacheKey, data);
console.log('[新缓存存入]', cacheKey);
return data;

} catch (error) {
console.error('请求失败:', error);
throw error;
}
}

这个基础版本存在三个明显问题:
1. 内存泄漏风险(缓存无限增长)
2. 缺乏缓存过期机制
3. 不同参数的同API请求会被视为不同请求

三、生产级缓存方案

我们需要更健壮的实现:

javascript
class RequestCache {
constructor(maxSize = 50, ttl = 60000) {
this.cache = new Map();
this.maxSize = maxSize;
this.ttl = ttl; // 默认1分钟
}

get(key) {
const entry = this.cache.get(key);
if (!entry) return null;

// 检查过期时间
if (Date.now() > entry.expireAt) {
  this.cache.delete(key);
  return null;
}
return entry.data;

}

set(key, data) {
// 执行LRU淘汰策略
if (this.cache.size >= this.maxSize) {
const oldestKey = this.cache.keys().next().value;
this.cache.delete(oldestKey);
}

this.cache.set(key, {
  data,
  expireAt: Date.now() + this.ttl
});

}

clear() {
this.cache.clear();
}
}

四、缓存策略进阶技巧

  1. 请求去重:当相同请求已经在进行时,不再发起新请求

javascript
const pendingRequests = new Map();

async function dedupedFetch(url) {
if (pendingRequests.has(url)) {
return pendingRequests.get(url);
}

const promise = fetch(url).then(res => res.json())
.finally(() => pendingRequests.delete(url));

pendingRequests.set(url, promise);
return promise;
}

  1. 分层缓存策略



    • 内存缓存:用于短期高频数据
    • SessionStorage:会话级缓存
    • IndexedDB:长期存储大型数据
  2. 缓存更新策略:javascript
    async function getWithCacheUpdate(url) {
    const cachedData = cache.get(url);
    const freshData = await fetch(url).then(res => res.json());

    // 后台静默更新缓存
    if (JSON.stringify(cachedData) !== JSON.stringify(freshData)) {
    cache.set(url, freshData);
    }

    return cachedData || freshData;
    }

五、实战中的注意事项

  1. 敏感数据缓存:切勿缓存认证令牌等敏感信息
  2. 缓存分区:按用户ID划分缓存空间,避免数据污染
  3. 缓存击穿防护:javascript
    async function safeGet(key, loader) {
    const value = cache.get(key);
    if (value !== undefined) return value;

    // 加锁防止缓存击穿
    const promise = loader();
    cache.set(key, promise); // 先存入Promise对象

    try {
    const result = await promise;
    cache.set(key, result); // 替换为实际结果
    return result;
    } catch (err) {
    cache.delete(key);
    throw err;
    }
    }

在Vue/React项目中,可以将缓存逻辑封装成自定义Hook或高阶组件。例如在React中:

jsx
function useCachedRequest(url) {
const [data, setData] = useState(null);
const cache = useContext(CacheContext);

useEffect(() => {
const cached = cache.get(url);
if (cached) {
setData(cached);
return;
}

fetch(url)
  .then(res => res.json())
  .then(json => {
    cache.set(url, json);
    setData(json);
  });

}, [url, cache]);

return data;
}

缓存策略需要根据具体业务场景调整。内容型网站可能采用长时间缓存,而实时交易系统则需要更短的缓存周期。关键在于找到性能体验与数据实时性的平衡点。

朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/37873/(转载时请注明本文出处及文章链接)

评论 (0)

人生倒计时

今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月

最新回复

  1. 强强强
    2025-04-07
  2. jesse
    2025-01-16
  3. sowxkkxwwk
    2024-11-20
  4. zpzscldkea
    2024-11-20
  5. bruvoaaiju
    2024-11-14

标签云