Sha*_*rma 5 javascript events caching worker service-worker
我有一个基于 service worker 的离线应用程序,它允许用户离线下载 pdf 文件。
有一个文本文件,其中包含特定格式的 pdf 文件的下载路径和文件标题(以及 css、js 和图像路径),应用程序通过 ajax 读取此文本文件并绘制所有可用 pdf 文件的列表(通过显示标题和下载链接)
在安装事件期间,Worker 读取相同的文件并将所有 pdf 文件与文本文件本身一起放入缓存中,以便这些文件可以离线使用。
当我用一些新的 pdf 文件更新文本文件时会出现问题,worker 能够更新缓存中更新的文本文件,因为应用程序向文件发出 ajax 请求,worker 能够通过 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)
})
)
})
Run Code Online (Sandbox Code Playgroud)
如果文本文件中有任何更新,有没有办法更新缓存中新添加的 pdf 文件?
这是一个简单的解决方案。如果fetch我检查是否是,request如果masterdata.txt是,则在覆盖之前,我会从旧文件response中获取旧文件,如果存在,我会比较两者以检查它们是否不同,这意味着添加了新文件,然后我将这些文件和将它们添加到.cachemasterdata.txtcachefetchcache
// 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);
})
);
});
Run Code Online (Sandbox Code Playgroud)
我想到了另一个解决方案,这取决于您如何更新masterdata.txt. 如果您确实从客户端添加新文件 URL,masterdata.txt则只需同时获取和缓存即可。