当前位置: 首页 > 知识库问答 >
问题:

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

小牛23113
2024-10-24

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

共有2个答案

宋奇希
2024-10-24

在 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');
  });
});
邵修诚
2024-10-24

在 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 请求的缓存和过期。上述代码示例提供了基本的框架,但你可能需要根据自己的具体需求进行调整和优化。

 类似资料:
  • 我有一个在数据库上运行查询的API。由于查询执行时间可能很长,比如3分钟到10分钟,我的负载平衡器返回“上游请求超时”,但我可以看到查询已提交到数据源,但对最终用户来说,它显示了错误的消息。如何应对这种情况? 我的职能

  • 这是我的example-default.xml, 但上面给出的Bean属性“CacheExpiryPolicy”不可写或具有无效的setter方法。setter的参数类型和getter的返回类型匹配吗? 我怎样才能解决这个问题?

  • 我想创建一个网站,即使当它的服务器离线时也可以工作——我发现这就是服务工人的目的。 当我重新加载带有service worker且没有连接的页面时,它工作正常。但是,轮班重新加载(例如,绕过缓存)会解除服务工作人员的防护,并出现“无法连接到服务器”错误。 我的问题是-我是否可以以某种方式防止轮班重新加载(shift f5、ctrl f5等)破坏服务人员,或者至少在不恢复连接的情况下使其恢复?

  • 我调用服务器数据通过使用ajax在index.html.它是完美的获取这些数据。现在,我正在和服务人员一起工作。我可以缓存所有的静态资产(图像,js,css),并在Chrome开发工具的应用程序选项卡中的缓存存储中检查这些缓存的资产。我可以在网络选项卡中看到这些资产也被缓存(磁盘缓存)。 现在,我想使用ServiceWorker缓存这些ajax响应(图像文件数组)。在“网络”选项卡中,我可以看到它

  • 请求缓存 支持请求缓存功能,支持对GET请求设置缓存访问,并设置有效期。 请求缓存仅对GET请求有效 有两种方式可以设置请求缓存: 路由设置 可以在路由规则里面调用cache方法设置当前路由规则的请求缓存,例如: // 定义GET请求路由规则 并设置3600秒的缓存 Route::get('new/:id','News/read')->cache(3600); 第二次访问相同的路由地址的时候,会自

  • 注意:“”表示我要在两个地址上侦听客户端。 server.py client.py

  • 问题内容: 看来我应该这样做: 通过将其设置为来配置dispatcherServlet 但是,考虑到我没有XML配置,或者代码中没有任何各种初始化程序类(此答案提到),该怎么做? 在一个类中,我有一个像这样的方法,当前不会被调用。 Spring Boot 1.2.7.RELEASE; 一个简单的设置与Spring REST指南并没有太大区别 。 问题答案: 选项1:Spring Boot属性(仅适

  • 问题内容: 我想知道如何以n为一组进行ajax调用。 这是我的用例: 我有一个显示使用情况数据的表。您可以钻取每一行,如果每行都有一个可以更深入钻取的公共属性,则可以选择一次钻取所有它们。对于每一行,都会进行ajax调用以获取要附加到表中的数据。 在某些情况下,最多可以同时钻取50行。可以想象,这给服务器带来了很大压力。我如何最好地以较小的批次发送这些呼叫,这些呼叫在等待这些批次之后才能启动? 我