0

我目前正在考虑将服务工作者添加到我正在构建的 Web 应用程序中。

这个应用程序本质上是一个收藏管理器。您可以 CRUD 各种类型的项目,它们通常紧密联系在一起(例如 A hasMany B hasMany C)。

sw-toolbox 提供了一个toolbox.fastest处理程序,它先到缓存然后再到网络(在 99% 的情况下,缓存会更快),在后台更新缓存。我想知道的是如何通知您有可用的新版本页面。我的意图是显示缓存的版本,然后,如果网络获取更新版本,建议用户刷新页面以查看最新的编辑。不久前我在YouTube 视频中看到了一些东西,但演示者不知道如何处理这个问题。

那可能吗?是否有一些事件处理程序或承诺可以绑定到请求,以便我知道何时检索到较新版本?然后我会在页面上发布一条消息以显示通知。

如果没有,我知道toolbox.networkFirst即使在 Lie-Fi 上,我也可以使用合理的超时时间来使页面可用,但这并不好。

4

1 回答 1

0

我刚刚偶然发现了 Mozilla Service Worker Cookbooj,它或多或少包含了我想要的东西:https ://serviceworke.rs/strategy-cache-update-and-refresh.html

以下是相关部分(不是我的代码:为方便起见,在此处复制)。

获取工作人员的方法

// On fetch, use cache but update the entry with the latest contents from the server.
self.addEventListener('fetch', function(evt) {
  console.log('The service worker is serving the asset.');
  // You can use respondWith() to answer ASAP…
  evt.respondWith(fromCache(evt.request));
  // ...and waitUntil() to prevent the worker to be killed until the cache is updated.
  evt.waitUntil(
    update(evt.request)
    // Finally, send a message to the client to inform it about the resource is up to date.
    .then(refresh)
  );
});

// Open the cache where the assets were stored and search for the requested resource. Notice that in case of no matching, the promise still resolves but it does with undefined as value.
function fromCache(request) {
  return caches.open(CACHE).then(function (cache) {
    return cache.match(request);
  });
}

// Update consists in opening the cache, performing a network request and storing the new response data.
function update(request) {
  return caches.open(CACHE).then(function (cache) {
    return fetch(request).then(function (response) {
      return cache.put(request, response.clone()).then(function () {
        return response;
      });
    });
  });
}

// Sends a message to the clients.
function refresh(response) {
  return self.clients.matchAll().then(function (clients) {
    clients.forEach(function (client) {
    // Encode which resource has been updated. By including the ETag the client can check if the content has changed.
      var message = {
        type: 'refresh',
        url: response.url,
        // Notice not all servers return the ETag header. If this is not provided you should use other cache headers or rely on your own means to check if the content has changed.
        eTag: response.headers.get('ETag')
      };

      // Tell the client about the update.
      client.postMessage(JSON.stringify(message));
    });
  });
}

处理“资源已更新”消息

navigator.serviceWorker.onmessage = function (evt) {
  var message = JSON.parse(evt.data);

  var isRefresh = message.type === 'refresh';
  var isAsset = message.url.includes('asset');
  var lastETag = localStorage.currentETag;

  // ETag header usually contains the hash of the resource so it is a very effective way of check for fresh content.
  var isNew =  lastETag !== message.eTag;

  if (isRefresh && isAsset && isNew) {
    // Escape the first time (when there is no ETag yet)
    if (lastETag) {
      // Inform the user about the update.
      notice.hidden = false;
    }
    //For teaching purposes, although this information is in the offline cache and it could be retrieved from the service worker, keeping track of the header in the localStorage keeps the implementation simple.
    localStorage.currentETag = message.eTag;
  }
};
于 2018-06-22T06:54:28.800 回答