【问题标题】:Service Worker with Multiple Caches具有多个缓存的 Service Worker
【发布时间】:2019-02-26 15:09:23
【问题描述】:

有很多示例可以使用类似于以下内容的单个缓存来初始化 Service Worker:

let cacheName = 'myCacheName-v1';
let urlsToCache = ['url1', 'url2', url3'];

self.addEventListener('install', function (event) {
  event.waitUntil(
    caches.open(cacheName).then(function (cache) {
      return cache.addAll(urlsToCache);
    }).then(function () {
      return this.skipWaiting();
    })
  );
});

我希望在我的 Service Worker 上初始化多个缓存。其动机是根据资产的变化趋势(例如,静态应用数据与 css、javascript 等)对资产进行分组。使用多个缓存,我可以更新单个缓存(通过版本化缓存名称)作为缓存中的文件更改。理想情况下,我希望设置类似于以下的结构:

let appCaches = [{
    name: 'core-00001',
    urls: [
      './',
      './index.html', etc...
    ]
  },
  {
    name: 'data-00001',
    urls: [
      './data1.json',
      './data2.json', etc...
    ]
  },
  etc...
];

到目前为止,我的最佳尝试类似于:

self.addEventListener('install', function (event) {
  appCaches.forEach(function (appCache) {
    event.waitUntil(
      caches.open(appCache.name).then(function (cache) {
        return cache.addAll(appCache.urls);
      }));
  });
  self.skipWaiting();
});

这种方法似乎有效。但是,对于服务人员和承诺,我仍然是新手。有些事情告诉我,这种方法有一个我太缺乏经验而无法识别的陷阱。有没有更好的方法来实现这一点?

【问题讨论】:

    标签: javascript service-worker


    【解决方案1】:

    最好在处理程序中只调用一次event.waitUntil,但好处是获得一个等待的 Promise 相对容易。

    类似的东西应该可以工作:

    event.waitUntil(Promise.all(
      myCaches.map(function (myCache) {
        return caches.open(myCache.name).then(function (cache) {
          return cache.addAll(myCache.urls);
        })
      )
    ));
    

    Promise.all 接受一个 Promises 数组,并且仅在 Array 中的所有 Promise 解析后才解析,这意味着 install 处理程序将等待所有缓存都初始化。

    【讨论】:

      【解决方案2】:

      谢谢pirxpilot!您的回答与JavaScript Promises: an Introduction 相结合,以及为了弄清楚如何将所有这些 Promises 链接在一起而进行的大量试验和错误导致了一个不错的小实现。

      我添加了仅缓存更改的要求。根据最佳实践,旧缓存在“激活”事件期间被删除。最终产品是:

      let cacheNames = appCaches.map((cache) => cache.name);
      
      self.addEventListener('install', function (event) {
        event.waitUntil(caches.keys().then(function (keys) {
          return Promise.all(appCaches.map(function (appCache) {
            if (keys.indexOf(appCache.name) === -1) {
              return caches.open(appCache.name).then(function (cache) {
                console.log(`caching ${appCache.name}`);
                return cache.addAll(appCache.urls);
              })
            } else {
              console.log(`found ${appCache.name}`);
              return Promise.resolve(true);
            }
          })).then(function () {
            return this.skipWaiting();
          });
        }));
      });
      
      self.addEventListener('activate', function (event) {
        event.waitUntil(
          caches.keys().then(function (keys) {
            return Promise.all(keys.map(function (key) {
              if (cacheNames.indexOf(key) === -1) {
                console.log(`deleting ${key}`);
                return caches.delete(key);
              }
            }));
          })
        );
      });
      

      【讨论】:

      • 那么在 fetch 事件期间,你如何决定打开哪个缓存并查看资源是否存在?
      • @booleanhunter caches.match 应该遍历所有缓存并尝试匹配。您可以将 cache.match 用于单个缓存。
      猜你喜欢
      • 2018-05-14
      • 2018-12-24
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      • 2018-02-19
      • 2016-10-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多