Javascript 我如何通知我的应用程序它';正在从服务工作者接收缓存响应?

Javascript 我如何通知我的应用程序它';正在从服务工作者接收缓存响应?,javascript,service-worker,Javascript,Service Worker,我想使用服务工作者缓存响应,这些响应可以在用户脱机或我的应用后端关闭时使用。出于用户体验的原因,我想向用户显示一个通知,通知用户当前无法访问应用程序的后端,而正在提供缓存内容。最好的方法是什么?我可以在服务人员的响应中添加一个标题,但我不确定这是“正确的方式”。。。似乎应该有一个更直接的模式。这是我的服务人员代码: self.addEventListener('fetch', event => { console.log(`fetch event`, event); event.r

我想使用服务工作者缓存响应,这些响应可以在用户脱机或我的应用后端关闭时使用。出于用户体验的原因,我想向用户显示一个通知,通知用户当前无法访问应用程序的后端,而正在提供缓存内容。最好的方法是什么?我可以在服务人员的响应中添加一个标题,但我不确定这是“正确的方式”。。。似乎应该有一个更直接的模式。这是我的服务人员代码:

self.addEventListener('fetch', event => {
  console.log(`fetch event`, event);
  event.respondWith(doFetch(event.request));
});

// fetch from network, fallback to cache
function doFetch(request) {
  return fetch(request)
    .then(response => {
      return caches.open(CACHE)
        .then(cache => {
          cache.put(request, response.clone());
          return response;
        })
    })
    .catch(error => {
      console.warn(`fetch to ${request.url} failed`, error);
      return fromCache(request);
    });
}

function fromCache(request) {
  return caches.open(CACHE)
    .then(cache => cache.match(request))
    .then(match => {
      if (match) {
        // response.clone doesn't work here because I need to modify it
        return cloneResponse(match);
      } else {
        throw new Error(`no match for ${request.url}`);
      }
    });
}
// this clones a response in a way that let's me modify it
function cloneResponse(response) {
  let init = {
    status: response.status,
    statusText: response.statusText,
    headers: { 'X-From-SW-Cache': 'true' }
  };

  response.headers.forEach((v, k) => {
    init.headers[k] = v;
  });

  return response.text().then((body) => new Response(body, init));
}

向响应添加标题肯定是一种选择

另一个要考虑的选项是将消息发送到客户端页面,让它知道正在使用缓存的响应。如果您想在重新使用网络后切换某个UI元素,则可以扩展该逻辑,将消息发送给客户端,让它知道何时使用了网络响应

以下是在您的服务人员中实现这一点的代码:

异步函数postToClient(客户端ID,消息){ const client=wait clients.get(clientId); client.postMessage(消息); } 异步函数响应逻辑(事件){ const cache=等待缓存。打开('cache-name'); 试一试{ const response=等待获取(event.request); 等待cache.put(event.request,response.clone()); event.waitill(postToClient(event.request.clientId,“FROM_NETWORK”); 返回响应; }捕获(错误){ const cachedResponse=等待cache.match(event.request); 如果(缓存响应){ event.waitUntil(postToClient(event.request.clientId,'FROM_CACHE'); 返回缓存响应; } 投掷误差; } } self.addEventListener('fetch',(事件)=>{ //检查这是否是对API的请求: 如果(event.request.url=='https://example.com/api') { 事件。响应(响应逻辑(事件)); } }); 然后在客户端页面上,您可以注册一个
消息
侦听器,通过显示或隐藏一些UI元素来响应来自服务人员的消息,具体取决于最后一次响应是来自网络还是缓存:

navigator.serviceWorker.addEventListener('message',(event)=>{
如果(event.data==='来自网络'){
//在UI中执行一些操作。
}else if(event.data==='FROM_CACHE'){
//在UI中执行一些操作。
}
});

@Taplar实际上不起作用。它抛出“构造“响应”失败:具有空主体状态的响应不能具有主体”,这很有意义。304响应的定义是空的。添加一个标题听起来很好。@Bergi在仔细考虑之后——我认为理想情况下后端会在所有响应上返回一个日期标题,但如果不可能,那么您必须修改响应并添加一个标题。