【问题标题】:Fetch returns 200 in service worker even if offline即使离线,Fetch 也会在 service worker 中返回 200
【发布时间】:2020-02-25 17:01:22
【问题描述】:

我希望我的 Angularjs (1.x) 应用程序有一个离线版本作为备用,以防没有网络或没有互联网服务。

我想要 service worker 的 fetch 事件监听器,尝试从网络中获取主页(当 request.mode == 'navigate' 时),如果失败则返回缓存版本。

出于某种原因,即使我已断开 wifi 连接或在“飞行模式”下运行,fetch 总是返回 StatusCode 200 OK。但它确实有效,如果我打开 Chrome 的 DevTools “网络 > 离线”模式

...我试过的:

我尝试使用“navigator.onLine”功能检测离线模式,但不可靠。

也尝试清除缓存,但什么都没有。。仍然返回原始的“在线”html文档。

还尝试将“cache-control: no-store, no-cache”标头传递给 fetch,结果相同..

self.addEventListener('fetch', function (event) {
  if (event.request.mode === 'navigate') {    
    event.respondWith(homeNetworkThenCache(event.request));
  } 
});

function homeNetworkThenCache(request){
  return fetch(request)
          .then(e => e)
          .catch(() => caches.match(offlineHomepageUrl));
}

预期行为:

如果没有互联网连接,我希望获取进入“catch”块,但它总是进入“.then(e => e)”...

..有什么想法吗?

【问题讨论】:

  • 您是否在 HTML 响应中设置了 Cache-Conrtol 标头?听起来您最终可能会从浏览器的“正常”HTTP 缓存中读取这些响应。
  • 当您输入 url 时,请求是由浏览器发出的。我在响应中看不到任何“Cache-control”标头。请求发送“Cache-Control: max-age=0”
  • 您没有将event.request 作为参数传递给homeNetworkThenCache(),但是?这是你的实际代码还是你只是解释它?
  • 谢谢 Jeff.. 我添加了 event.request 参数,这是一个简化版本,而不是确切的真实代码

标签: caching fetch service-worker progressive-web-apps offlineapps


【解决方案1】:

如果您正在寻找一个只是实现离线回退页面的示例服务工作者,您可以use this one,它还将执行诸如启用导航预加载(如果支持)之类的操作:

const OFFLINE_VERSION = 1;
const CACHE_NAME = 'offline';
// Customize this with a different URL if needed.
const OFFLINE_URL = 'offline.html';

self.addEventListener('install', (event) => {
  event.waitUntil((async () => {
    const cache = await caches.open(CACHE_NAME);
    // Setting {cache: 'reload'} in the new request will ensure that the response
    // isn't fulfilled from the HTTP cache; i.e., it will be from the network.
    await cache.add(new Request(OFFLINE_URL, {cache: 'reload'}));
  })());
});

self.addEventListener('activate', (event) => {
  event.waitUntil((async () => {
    // Enable navigation preload if it's supported.
    // See https://developers.google.com/web/updates/2017/02/navigation-preload
    if ('navigationPreload' in self.registration) {
      await self.registration.navigationPreload.enable();
    }
  })());

  // Tell the active service worker to take control of the page immediately.
  self.clients.claim();
});

self.addEventListener('fetch', (event) => {
  // We only want to call event.respondWith() if this is a navigation request
  // for an HTML page.
  if (event.request.mode === 'navigate') {
    event.respondWith((async () => {
      try {
        // First, try to use the navigation preload response if it's supported.
        const preloadResponse = await event.preloadResponse;
        if (preloadResponse) {
          return preloadResponse;
        }

        const networkResponse = await fetch(event.request);
        return networkResponse;
      } catch (error) {
        // catch is only triggered if an exception is thrown, which is likely
        // due to a network error.
        // If fetch() returns a valid HTTP response with a response code in
        // the 4xx or 5xx range, the catch() will NOT be called.
        console.log('Fetch failed; returning offline page instead.', error);

        const cache = await caches.open(CACHE_NAME);
        const cachedResponse = await cache.match(OFFLINE_URL);
        return cachedResponse;
      }
    })());
  }

  // If our if() condition is false, then this fetch handler won't intercept the
  // request. If there are any other fetch handlers registered, they will get a
  // chance to call event.respondWith(). If no fetch handlers call
  // event.respondWith(), the request will be handled by the browser as if there
  // were no service worker involvement.
});

【讨论】:

  • 感谢杰夫的努力!真的很感激..我试过'navigationPreload'功能,我不知道。不过我还不能解决这个问题。正如您之前提到的,我几乎可以肯定网络调用正在返回 http-cached 版本。但我不知道如何绕过它,因为原始请求也来自浏览器本身(不能在那里设置无缓存标头)
  • Cache-Control 标头可以在请求或响应中设置。 (具有不同的语义。)虽然是浏览器发出请求,但您可以控制服务器的响应,您可以在该响应上设置Cache-Control: no-cache。 developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
猜你喜欢
  • 2017-04-02
  • 1970-01-01
  • 2017-09-07
  • 1970-01-01
  • 2017-07-06
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
  • 2017-05-18
相关资源
最近更新 更多