首页 文章

服务工作者 - 首先通过网络缓存并回退到静态页面

提问于
浏览
2

我想在我的网站上添加服务工作者,为我的网站用户提供良好的离线体验 . (网站后端是PHP)

我仍然是Javascript承诺和服务工作者的新手,但这是我到目前为止所达到的:

我的 index.php 页面有这个脚本来注册服务工作者

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

和服务工作者文件 i use the following code

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)它注册服务工作者并获取我的静态缓存文件的副本 . (2)激活新的服务工作程序时,它会删除旧的缓存 . (3)对于每个新请求,它首先从网络获取,如果成功,则在缓存中放入一个新的请求副本 . (4)如果在离线时未能发出网络请求,则向用户返回最后一个网络请求的新副本 .

我希望实现她的是(如果 - 用户离线 - 并尝试请求不在缓存中的新页面,他应该被重定向到保存在静态缓存中的(offline.php)页面) like the following

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

但我有一个问题,我不知道我应该在(fetch)步骤中的我的(sw.js)文件中添加此行,我真的尝试阅读更多关于服务工作者和Javascript承诺,并尝试多次添加此行在我的代码中不同的地方,但每次都没有使它工作,但错过了前一个场景或保持场景但未能实现这一目标 .

非常感谢您的帮助和许多提前感谢 .

1 回答

  • 9

    在你的fetch事件监听器中:

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

    事实上,如果没有从缓存中找到匹配项,则caches.match(event.request)实际上返回一个Promise,解析为undefined .

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

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

相关问题