javascript - 如何通过服务 worker 更新缓存的资源

标签 javascript events caching service-worker worker

我有一个基于服务 worker 的离线应用程序,它允许用户离线下载 pdf 文件。
有一个文本文件,其中包含特定格式的 pdf 文件的下载路径和文件标题(以及 css、js 和图像路径),应用程序通过 ajax 读取此文本文件并绘制所有可用 pdf 文件的列表(通过显示标题和下载链接)
Worker 在安装事件期间读取相同的文件并将所有 pdf 文件与文本文件本身一起放入缓存中,以便这些文件可以脱机使用。
当我用一些新的 pdf 文件更新文本文件时会出现问题,工作人员能够更新缓存中更新的文本文件,因为应用程序向文件发出 ajax 请求,工作人员能够通过 fetch 事件在缓存中更新它,但新添加的 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如果是这样,在我覆盖 response 之前在 cache我得到旧的 masterdata.txt来自 cache如果存在,我比较两者以检查它们是否不同,这意味着添加了新文件然后我 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从客户端你可以简单地同时获取和缓存。

关于javascript - 如何通过服务 worker 更新缓存的资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62966267/

相关文章:

JavaScript 函数 ID

javascript - 在内部 promise 解决之前 promise 解决

linux kmalloc 在 slab 中超过 8192

python - Django 中 locmem 缓存的内容?

caching - 当 Varnish 缓存已满时会发生什么?

javascript - 从 Busboy 到 MongoDB 的 FileStream

javascript - D3js 外部限制

vb.net - 如何检查是否会引发事件?

java - 获取鼠标单击事件的正确结果

javascript - 单击事件和命名空间单击事件 - 哪个首先触发并将 stopPropagation() 取消其中一个?