我有一个基于服务 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/