当前位置: 首页 > 知识库问答 >
问题:

如何通过服务工作者更新缓存的资源

石喜
2023-03-14

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

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

在安装过程中,工作人员读取相同的文件,并将所有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文件?

共有1个答案

微生新霁
2023-03-14

这里有一个简单的解决方案。在获取事件中,我检查请求是否为masterdata.txt,如果是,在覆盖缓存中的响应之前,我得到旧的<代码>masterdata.txt从缓存,如果它存在,我会比较两者,以检查它们是否不同,这意味着有新的文件添加,然后我获取这些文件并将它们添加到缓存.

// 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);
      })
  );
});

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

 类似资料:
  • 我使用带有sw工具箱库的service worker。我的PWA缓存除API查询(图像、css、js、html)之外的所有内容。但是如果有一天某些文件会被更改呢。或者如果服务人员。js将被更改。应用程序应该如何知道文件中的更改? 我的服务人员。js: 我不知道在PWA中更新缓存的常用方法是什么。也许PWA应该在后台发送AJAX请求并检查UI版本?

  • 我试图安装一个简单的ServiceWorker,但旧的,Django Web应用程序。我开始使用Chrome团队的示例读取缓存示例 这很好,但并不理想,因为如果需要,我想更新缓存。根据阅读此处所有其他服务人员的答案,有两种推荐方法。 > 使用一些服务器端逻辑来知道您显示的内容何时更新,然后更新您的服务辅助角色以更改所述内容。例如,这就是sw-preache所做的。 只要在需要更新资源时更新serv

  • 因此,我有一个带有服务工作者的HTML页面,服务工作者缓存索引。html和我的JS文件。 问题是当我更改JS时,更改不会直接显示在客户端浏览器上。当然,在chrome开发工具中,我可以禁用缓存。但是在Chrome Mobile,我该怎么做呢? 我试图访问站点设置并点击CLEAR%RESET按钮。但它仍然从缓存加载旧页面/加载。我试图使用其他浏览器或铬隐姓埋名,它加载新的页面。 然后,我尝试清除我的

  • 我使用sw-precache生成Polymer-CLI构建过程中的服务工作,因此它旨在更新更新文件的散列,以表示需要更新缓存。但是缓存中没有替换我更新的内容,因此如果我使用ctrl-r刷新,它将获得旧版本,但如果使用ctrl-shift-r刷新,它将获得新版本。原因可能是我的服务人员没有更新。 这份文件说 如果与当前相比,服务辅助程序文件中甚至有一个字节的差异,它就认为它是新的。 ,但如果我的新服

  • 我将React应用程序转换为PWA,它的工作部分正常。 我遵循了本教程:https://medium.com/@toricpope/transform-a-react-app-to-a-progressive-web-app-pwa-dea336bd96e6 然而,本文只展示了如何缓存静态数据,我还需要存储来自服务器的数据,我可以按照本文第一个答案的说明来做:如何将API中的数据缓存到React

  • 我读过的一些文章建议由ServiceWorker(WebCacheAPI)缓存的项永远存储在系统中。我遇到过这样一种情况,当用户在很长一段时间后重新访问我的网站时,一些缓存的资源会被自动收回(~ 如果是这种情况,那么浏览器如何决定它必须删除哪些资源?我是否可以告诉浏览器,如果它正在从缓存中删除某些内容,则删除使用相同缓存名称缓存的所有内容?