# 缓存与重复请求优化

URL: https://caijiao.org/axios/best-practices/cache
Source: docs/axios/best-practices/cache.md
Description: 本章节介绍如何在前端项目中使用 Axios 优化请求缓存与防止重复请求，包括浏览器缓存、内存缓存、请求去重策略、拦截器结合缓存、缓存过期处理等方法，帮助提高接口请求效率、减少冗余流量，提升用户体验和应用性能。

在大型前端项目中，频繁请求相同接口可能导致性能下降和不必要的网络流量。
Axios 提供了多种方式结合缓存策略与请求去重，优化前端性能。

## 一、为什么需要缓存与请求去重

* 减少相同接口的重复请求，降低服务器压力。
* 提升用户体验，尤其是在慢网或移动端。
* 避免多次重复请求导致的数据冲突或界面闪烁。

## 二、浏览器缓存机制

1. 利用 HTTP 缓存头：

   * `Cache-Control`：控制缓存策略，如 `max-age`、`no-cache`。
   * `ETag`：资源标识符变化时更新缓存。
   * `Last-Modified`：资源修改时间。

2. Axios 可结合 `If-None-Match` / `If-Modified-Since` 头实现条件请求：

```js
axios.get('/api/data', {
  headers: {
    'If-None-Match': cachedETag
  }
});
```

## 三、内存缓存（前端请求去重）

使用简单对象或 Map 缓存请求结果：

```js
const cache = new Map();

async function fetchWithCache(url) {
  if (cache.has(url)) {
    return cache.get(url);
  }
  const response = await axios.get(url);
  cache.set(url, response);
  return response;
}
```

## 四、结合拦截器实现全局缓存

```js
const cacheStore = new Map();

axios.interceptors.request.use(config => {
  const key = config.url + JSON.stringify(config.params || {});
  if (cacheStore.has(key)) {
    config.adapter = () => {
      return Promise.resolve(cacheStore.get(key));
    };
  }
  return config;
});

axios.interceptors.response.use(response => {
  const key = response.config.url + JSON.stringify(response.config.params || {});
  cacheStore.set(key, response);
  return response;
});
```

## 五、防止重复请求

* 对同一 URL 和参数的请求，在前一个未完成时阻止再次发送。

```js
const pending = new Map();

function requestWithDedup(config) {
  const key = config.url + JSON.stringify(config.params || {});
  if (pending.has(key)) {
    return pending.get(key);
  }
  const request = axios(config).finally(() => pending.delete(key));
  pending.set(key, request);
  return request;
}
```

## 六、缓存过期与更新策略

* 可设置时间戳过期：

```js
const cache = new Map();

function fetchWithExpiry(url, ttl = 5000) {
  const now = Date.now();
  const cached = cache.get(url);
  if (cached && (now - cached.time < ttl)) {
    return Promise.resolve(cached.response);
  }
  return axios.get(url).then(res => {
    cache.set(url, { response: res, time: now });
    return res;
  });
}
```

* 支持手动清理或基于版本号更新缓存。

## 七、小结

优化缓存和防止重复请求，可以显著提升前端性能与用户体验。
最佳实践：

* 静态数据优先使用浏览器缓存。
* 动态数据结合内存缓存和请求去重。
* 使用拦截器统一管理缓存逻辑。
* 对幂等请求安全重试，对非幂等请求谨慎。
