javascript 检测 Service Worker 离线状态的最佳实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46036897/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 06:24:02  来源:igfitidea点击:

Best practices for detecting offline state in a service worker

javascriptofflineservice-workerprogressive-web-apps

提问by Kaivosukeltaja

I have a service worker that is supposed to cache an offline.htmlpage that is displayed if the client has no network connection. However, it sometimes believes the navigator is offline even when it is not. That is, navigator.onLine === false. This means the user may get offline.htmlinstead of the actual content even when online, which is obviously something I'd like to avoid.

我有一个服务工作者,它应该缓存一个offline.html页面,如果客户端没有网络连接,则显示该页面。但是,它有时会认为导航器处于离线状态,即使它不是。也就是说,navigator.onLine === false。这意味着用户offline.html即使在线时也可能获得而不是实际内容,这显然是我想避免的。

This is how I register the service worker in my main.js:

这就是我在我的 中注册服务工作者的方式main.js

// Install service worker for offline use and caching
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {scope: '/'});
}

My current service-worker.js:

我的当前service-worker.js

const OFFLINE_URL = '/mysite/offline';
const CACHE_NAME = 'mysite-static-v1';

self.addEventListener('install', (event) => {
  event.waitUntil(
    // Cache the offline page when installing the service worker
    fetch(OFFLINE_URL, { credentials: 'include' }).then(response =>
      caches.open(CACHE_NAME).then(cache => cache.put(OFFLINE_URL, response)),
    ),
  );
});

self.addEventListener('fetch', (event) => {
  const requestURL = new URL(event.request.url);

  if (requestURL.origin === location.origin) {
    // Load static assets from cache if network is down
    if (/\.(css|js|woff|woff2|ttf|eot|svg)$/.test(requestURL.pathname)) {
      event.respondWith(
        caches.open(CACHE_NAME).then(cache =>
          caches.match(event.request).then((result) => {
            if (navigator.onLine === false) {
              // We are offline so return the cached version immediately, null or not.
              return result;
            }
            // We are online so let's run the request to make sure our content
            // is up-to-date.
            return fetch(event.request).then((response) => {
              // Save the result to cache for later use.
              cache.put(event.request, response.clone());
              return response;
            });
          }),
        ),
      );
      return;
    }
  }

  if (event.request.mode === 'navigate' && navigator.onLine === false) {
    // Uh-oh, we navigated to a page while offline. Let's show our default page.
    event.respondWith(caches.match(OFFLINE_URL));
    return;
  }

  // Passthrough for everything else
  event.respondWith(fetch(event.request));
});

What am I doing wrong?

我究竟做错了什么?

采纳答案by Jeff Posnick

navigator.onLineand the related events can be useful when you want to update your UI to indicate that you're offline and, for instance, only show content that exists in a cache.

navigator.onLine当您想要更新 UI 以指示您处于离线状态时,相关事件会很有用,例如,仅显示缓存中存在的内容。

But I'd avoid writing service worker logic that relies on checking navigator.onLine. Instead, attempt to make a fetch()unconditionally, and if it fails, provide a backup response. This will ensure that your web app behaves as expected regardless of whether the fetch()fails due to being offline, due to lie-fi, or due to your web server experiencing issues.

但我会避免编写依赖于检查的服务工作者逻辑navigator.onLine。相反,尝试fetch()无条件地做出响应,如果失败,则提供备用响应。这将确保您的 web 应用程序按预期运行,无论fetch()失败是由于离线、lie-fi还是由于您的 web 服务器遇到问题。

// Other fetch handler code...

if (event.request.mode === 'navigate') {
  return event.respondWith(
    fetch(event.request).catch(() => caches.match(OFFLINE_URL))
  );
}

// Other fetch handler code...