Service Worker 即时声明页面的最佳实践 [英] Best practice for instant claim of a page by Service Worker

查看:35
本文介绍了Service Worker 即时声明页面的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于应用程序和用户体验的性质,我目前设置了一个 Service Worker 来立即声明页面.

I currently have a service worker set up to claim the page immediately, due to the nature of the application and user experience.

由于这个应用程序是从 AppCache 转换过来的,它为每个用户创建了一个动态 Manifest 文件,我发现最好的方法是将此 Manifest 文件解析为 JSON 数组并将其发送给 Service Worker 以便缓存它.问题是我需要等到 Service Worker 处于活动状态才能接收此数组.

As this application is converting over from AppCache, which had a dynamic Manifest file created for each user, I found that the best method was to Parse this Manifest file to a JSON array and send it to the Service Worker in order to cache it. The problem being I need to wait until the Service Worker is active before it can receive this array.

我目前已将函数的超时设置为 10000(见下文),但成功率不是 100%.我经常发现在这个 10000 超时结束之前没有激活 Service Worker 导致错误:TypeError: navigator.serviceWorker.controller is null".

I currently have set a timeout on the function to 10000 (see below), but the success rate is not 100%. I often find that the Service Worker is not activated before the end of this 10000 timeout resulting in an error: "TypeError: navigator.serviceWorker.controller is null".

//Get Request - Service Worker Preperation 
setTimeout(function getRequest() {
  console.log("APP: Enetered getRequest() Method");
  $.ajax({
    type : "GET",
    url : "https://ExampleURL/App/" + 
    localStorage.getItem("user") + ".manifest",
    contentType: "text/plain",
    async : false,
    success : function(response) {
        var myArray = listToArray(response, '\n'); 
        send_message_to_sw(myArray);
    },
    error : function(msg) {
        console.log("ERROR: " + msg);
     }
    });
}, 10000);

我的问题是检查 Service Worker 是否处于活动状态的最佳做法是什么,还是应该增加超时时间?

My question is what is the best practice for checking if the Service worker is active, or should I just increase the amount of time in the timeout?

我在下面附上相关的 Service Worker 代码,以防我设置立即索赔的方式有问题.

I am attaching the relevant Service Worker code below incase there is a problem with the way I have set up the immediate claim.

// INSTALL
self.addEventListener('install', function(event) {
  console.log('[ServiceWorker] Installed version', version);
  event.waitUntil(
    caches.open(version).then(function(cache) {
        console.log('[ServiceWorker] Cached cachedFiles for', version);

        return cache.addAll(cacheFiles);

    }).then(function() {

      console.log('[ServiceWorker] Skip waiting on install');
      return self.skipWaiting();
    })
  );
});


 //ACTIVATE
 self.addEventListener('activate', function(event) {

  self.clients.matchAll({
    includeUncontrolled: true
  }).then(function(clientList) {
    var urls = clientList.map(function(client) {
      return client.url;
    });
    console.log('[ServiceWorker] Matching clients:', urls.join(', '));
  });

  event.waitUntil(

    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheName !== version) {
            console.log('[ServiceWorker] Deleting old cache:', cacheName);
            return caches.delete(cacheName);
          }
        })
      );
    }).then(function() {


      console.log('[ServiceWorker] Claiming clients for version', version);
      return self.clients.claim();
    })
  );
});


//RECIEVE DATA FROM JAVASCRIPT FILE
self.addEventListener('message', function(event){
  console.log("SW Received Message: " + event.data);
  var fullArray = [];

  var che = event.data;
  fullArray = che.splice(',');
  console.log("SWChe2: " + fullArray);
  var result = fullArray.slice(1,-1);


  caches.open(version + 'Manifest')
  .then(function(cache) {
    return cache.addAll(result);
 });
});

推荐答案

navigator.serviceWorker.ready 是客户端页面可以等待的承诺,并且会在存在范围包含当前页面的活动 Service Worker 时解析.

navigator.serviceWorker.ready is a promise that client pages can wait on, and will resolve when there's an active service worker whose scope encompasses the current page.

navigator.serviceWorker.ready.then(registration => {
  // Do something, confident that registration corresponds to
  // an active SW's registration.
});

但是……有两件事.

  • You can add items using the Cache Storage API from the context of your page, without having to send a message to a service worker. window.caches.open('my-cache-name') will give you access to the same cache that a service worker can use.

如果您有一组总是需要缓存的资源,最好将它们缓存在您的 install 处理程序中.这可确保除非缓存所需文件,否则 Service Worker 不会完成安装.您可以在 install 处理程序中使用 fetch() 来检索需要预缓存的资源的 JSON 清单,以及 IndexedDB(而不是 localStorage>,它不会暴露给服务工作者)来存储当前用户的名称.只要确保如果你走这条路,你会使用 event.waitUntil() 来延迟 install 处理程序的完成,直到全套操作成功.>

If you've got a set of resources that always need to be cached, you're probably better off caching them inside of your install handler. That ensures that the service worker won't finish installation unless the required files are cached. You can use fetch() inside of your install handler to retrieve a JSON manifest of resources that need to be precached, and IndexedDB (instead of localStorage, which isn't exposed to service workers) to store the name of the current user. Just make sure that if you go this route, you make use of event.waitUntil() to delay the install handler's completion until the full set of operations is successful.

这篇关于Service Worker 即时声明页面的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆