javascript - Service Worker - 首先是网络然后缓存回退到静态页面

标签 javascript promise service-worker progressive-web-apps offline-caching

我想在我的站点中添加 Service Worker,以便为我的站点用户提供良好的离线体验。 (网站后台为PHP)

我对 Javascript promises 和 service workers 还是个新手,但这是我到目前为止所达到的:

我的 index.php 页面有这个脚本来注册 service worker

<script> 
    if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js')};
</script>

对于服务 worker 文件我使用以下代码

var CACHE_STATIC_NAME = 'static-v74';
var CACHE_DYNAMIC_NAME = 'dynamic-v74';

self.addEventListener('install', function (event) {
  console.log('Installing Service Worker ...', event);
  event.waitUntil(
    caches.open(CACHE_STATIC_NAME)
      .then(function (cache) {
        console.log('Precaching App Shell');
        cache.addAll([
          'offline.php', // offline page
          'assets/bundle.css',
          'assets/bundle.js',
          'assets/images/logo.jpg',
          'assets/images/favicon.ico'
        ]);
      })
  )
});

self.addEventListener('activate', function (event) {
  console.log('Activating Service Worker ....', event);
  event.waitUntil(
    caches.keys()
      .then(function (keyList) {
        return Promise.all(keyList.map(function (key) {
          if (key !== CACHE_STATIC_NAME && key !== CACHE_DYNAMIC_NAME) {
            console.log('Removing old cache.', key);
            return caches.delete(key);
          }
        }));
      })
  );
  return self.clients.claim();
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    // Try the network
    fetch(event.request)
      .then(function(res) {
        return caches.open(CACHE_DYNAMIC_NAME)
          .then(function(cache) {
            // Put in cache if succeeds
            cache.put(event.request.url, res.clone());
            return res;
          })
      })
      .catch(function(err) {
          // Fallback to cache
          return caches.match(event.request);
      })
  );
});

事实上,这段代码按预期工作正常:

(1) 它注册服务 worker 并获取我的静态缓存文件的副本。 (2) 当激活一个新的 service worker 时,它会删除旧的缓存。 (3) 对于每个新请求,它首先从网络中获取,如果成功,它会将请求的新副本放入缓存中。 (4) 如果在离线时未能发出网络请求,则返回用户上次网络请求的最新副本。

我想要实现的是(如果 - 用户离线 - 并尝试请求一个不在缓存中的新页面,他应该被重定向到保存在静态中的(offline.php)页面缓存)如下所示

// If both (network & cache) fail, show a generic fallback:
return caches.match('offline.php');

但我有一个问题,我不知道我应该在 (sw.js) 文件中的 (fetch) 步骤中将这一行添加到什么位置,我真的尝试阅读更多关于服务 worker 和 Javascript promise 的信息并尝试添加这个在我的代码中的不同位置多次行,但每次都没有使它工作但错过了以前的场景或保持场景但未能实现这个目标。

非常感谢您的帮助,并提前致谢。

最佳答案

在你的 fetch 事件监听器中:

.catch(function(err) {
      // Fallback to cache
      return caches.match(event.request);
  })

caches.match(event.request) 实际上会返回一个 Promise,如果未从缓存中找到匹配项,该 Promise 将解析为 undefined。

检查未定义并从缓存中返回 offline.php:

return caches.match(event.request)
  .then(function(res){
    if (res === undefined) { 
      // get and return the offline page
    } 
    return res;
})

关于javascript - Service Worker - 首先是网络然后缓存回退到静态页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50074992/

相关文章:

java - 使用 SQL 数据库中的值过滤 JSP 上的表值

javascript - 从 mysql 数据库加载特定行数并添加加载更多功能

javascript - 如何修复我的 promise return here for this function?

javascript - 浏览器关闭时推送通知不起作用

javascript - 在 http 上工作的 Service Worker

javascript - Three.js顶点着色器: update attributes and how to save a value for the next processing round

javascript - 解析云代码回调不起作用

javascript - 拒绝然后解决 Q Promise

javascript - 在 promise 中中止 ajax 请求

caching - 使用工作箱时如何忽略缓存网址中的网址查询字符串?