如何在 Service Worker 中处理 API 请求缓存和过期策略?

当你在 Service Worker 中缓存 API 数据时,如何管理缓存过期、更新等策略?

阅读 787
avatarAI BotBETA

在 Service Worker 中处理 API 请求的缓存和过期策略,通常涉及几个关键步骤:拦截网络请求、检查缓存状态、更新缓存以及设置缓存过期策略。以下是一些基本步骤和示例代码,展示如何在 Service Worker 中实现这些功能:

1. 拦截网络请求

使用 Service Worker 的 fetch 事件来拦截所有或特定网络请求。

self.addEventListener('fetch', function(event) {
  const request = event.request;
  // 检查请求的 URL 是否需要被缓存处理
  if (shouldCache(request.url)) {
    event.respondWith(cacheAndNetworkRace(request));
  } else {
    // 不需要缓存的请求直接放行
    event.respondWith(fetch(request));
  }
});

function shouldCache(url) {
  // 根据 URL 判断是否需要缓存
  return url.startsWith('https://api.example.com/');
}

2. 缓存和网络竞争

实现一个 cacheAndNetworkRace 函数,该函数尝试从缓存获取资源,同时发起网络请求。一旦其中一个响应返回,就使用它,但网络请求仍然继续以更新缓存。

async function cacheAndNetworkRace(request) {
  try {
    const cacheResponse = await caches.match(request);
    if (cacheResponse) {
      // 尝试从网络获取最新版本,但不等待它完成
      fetch(request).then(response => {
        if (response.ok) {
          caches.open('my-cache-name').then(cache => {
            cache.put(request, response.clone());
          });
        }
      });
      return cacheResponse;
    }

    const networkResponse = await fetch(request);
    if (!networkResponse.ok) {
      throw new Error('Network response was not ok');
    }

    // 缓存响应
    const cache = await caches.open('my-cache-name');
    cache.put(request, networkResponse.clone());

    return networkResponse;
  } catch (error) {
    // 处理错误
    console.error('Fetch error:', error);
    throw error;
  }
}

3. 设置缓存过期策略

缓存的过期策略可以在存储缓存项时设置,但 Service Workers 原生不支持设置 TTL(Time-To-Live)。你需要自己管理过期逻辑。

一种方法是在缓存时添加一个时间戳,并在每次请求时检查时间戳来决定是否从网络重新获取数据。

async function updateWithTimestamp(request, response) {
  const cache = await caches.open('my-cache-name');
  // 将响应和时间戳一起存储
  const timestampedResponse = new Response(response.body, response);
  timestampedResponse.headers.append('X-Timestamp', new Date().toISOString());
  cache.put(request, timestampedResponse);
}

// 在获取缓存时检查时间戳
async function checkAndRefreshIfNeeded(request) {
  const cacheResponse = await caches.match(request);
  if (cacheResponse && !isExpired(cacheResponse)) {
    return cacheResponse;
  }
  // 如果过期,则发起网络请求并更新缓存
  // 这里使用 cacheAndNetworkRace 或直接 fetch 更新
}

function isExpired(response) {
  const timestamp = new Date(response.headers.get('X-Timestamp'));
  // 假设我们设置 1 小时过期
  return (new Date() - timestamp) / 36e5 > 1;
}

注意:Response 对象是不可变的,所以你需要创建一个新的 Response 对象来添加或修改头部信息。

总结

通过拦截请求、管理缓存和网络竞争,以及设置缓存过期策略,你可以有效地在 Service Worker 中处理 API 请求的缓存和过期。上述代码示例提供了基本的框架,但你可能需要根据自己的具体需求进行调整和优化。

1 个回答

在 Service Worker 中缓存 API 数据时,可以通过 Cache-Controlstale-while-revalidate 等 HTTP 头来管理缓存过期策略。另外,你可以手动在 Service Worker 中设置缓存的有效期,并在过期时自动更新:

caches.open('api-cache').then(cache => {
  cache.add('/api/data').then(() => {
    console.log('API data cached');
  });
});
推荐问题
宣传栏