如何通过 Service Worker 更新缓存资源

How to update cached resource by service worker

我有一个基于 service worker 的离线应用程序,它允许用户离线下载 pdf 文件。

有一个文本文件,其中包含特定格式的 pdf 文件的下载路径和文件标题(以及 css、js 和图像路径),应用程序通过 ajax 并绘制所有可用 pdf 文件的列表(通过显示标题和下载 link)

工作人员在安装过程中读取同一个文件并将所有 pdf 文件与文本文件本身一起放入缓存中,以便这些文件可以脱机使用。

当我用一些新的 pdf 文件更新文本文件时出现问题,工作人员能够在缓存中更新更新的文本文件,因为应用程序向文件发出 ajax 请求并且工作人员能够通过获取事件在缓存中更新它,但新添加的 PDF 文件未添加到缓存中,因为这些文件未触发获取。

// function to register worker add files in the cache 
this.addEventListener('install', event => {
    const client = clients.get(event.clientId);
    fetch('masterdata.txt')
        .then(
            function(response) {
                response.text().then(function(text) {
                    var documentFileArray = parseString(text);
                    var cacheDocs = [];
                     clients.claim();
                    var  count = 0;
                     caches.open(currentCache.offline).then(function(cache) {
                         var total_files = documentFileArray.length;
                         for(var i =0;i<total_files;i++){                            
                             cache.add(documentFileArray[i]).then(function(){   
                                 count++
                                 var data = {'count':count,'total':total_files}
                                 passMesagetoClient(clients,data)                            
                             })
                         }
                    })
                })
            }
        )
        .catch(function(err) {
            //console.log('Fetch Error :-S', err);
            clients.claim();
            passMesagetoClient(clients,'failed');
        });
});


//comman function to let client know service worker done caching files 
function passMesagetoClient(client,data){   
    client.matchAll().then(all => {
        all.map(client => {         
                client.postMessage({"status":"success","data":data})
            })
    }); 
}

//this will check and provide the files from cache if network not avalible 
this.addEventListener("fetch", function(event) {
    //var url = event.request.url;
       clients.claim();
       passMesagetoClient(clients,'success');
                        
        event.respondWith(
            fetch(event.request).then(function(response) {
                return caches.open(currentCache.offline).then(function(cache) {
                    return cache.put(event.request, response.clone()).then(function() {
                        return response
                    })
                })
            }).catch(function(e) {
                //console.log(e);
                return caches.match(event.request)
            })
        )
   
})

如果文本文件中有任何更新,是否有任何方法可以更新缓存中新添加的 pdf 文件?

这是一个简单的解决方案。在 fetch 事件中,我检查 request 是否用于 masterdata.txt,如果是,则在覆盖 cache 中的 response 之前,我得到旧的 [=来自 cache 的 13=],如果它存在,我比较两者以检查它们是否不同,这意味着添加了新文件,然后我 fetch 这些文件并将它们添加到 cache

// add the files in the array to the cache
async function cacheFiles(filesArray) {
  const count = 0;
  const cache = await caches.open(currentCache.offline);
  const totalFiles = filesArray.length;
  for (let i = 0; i < totalFiles; i++) {
    await cache.add(filesArray[i]);
    count++;
    const data = { count: count, total: totalFiles };
    passMesagetoClient(clients, data);
  }
}

// this will check and provide the files from cache if network not avalible
this.addEventListener("fetch", function(event) {
  clients.claim();
  passMesagetoClient(clients, "success");

  event.respondWith(
    fetch(event.request)
      .then(async function(newResponse) {
        // If this is the text file
        if (event.request.url.includes("masterdata.txt")) {
          // try to get the text file from the cache
          const cachedResponse = await caches.match(event.request);

          // If it exists
          if (cachedResponse) {
            // convert both responses to text
            const cachedText = await cachedResponse.text();
            const text = await newResponse.text();
            // if they are different
            if (cachedText !== text) {
              // If you can compare the old and new text to get the new urls
              // If you can't just compare the two arrays as following
              const oldFileArray = parseString(cachedText);
              const fileArray = parseString(text);
              // get the new urls
              const newFileArray = fileArray.filter(
                f => !oldFileArray.includes(f)
              );
              // fetch and cache them like you did in the install event
              await cacheFiles(newFileArray);
            }
          }
        }
        // add the new response to the cache
        const cache = await caches.open(currentCache.offline);
        cache.put(event.request, newResponse.clone());
        return newResponse;
      })
      .catch(function(e) {
        // console.log(e);
        return caches.match(event.request);
      })
  );
});

我想到了另一个解决方案,这取决于您如何更新 masterdata.txt。如果您确实从客户端将新文件 URL 添加到 masterdata.txt,您可以简单地同时获取和缓存。