![](/img/trans.png)
[英]How to respond to fetch event for a navigation in service worker?
[英]Service Worker Respond To Fetch after getting data from another worker
我正在使用服务工作者拦截对我的请求,并通过与Web工作者(也是从同一父页面创建)进行通信来提供对获取请求的响应。 我使用消息通道在工作者和服务工作者之间进行直接通信。 这是我写的一个简单的POC:
var otherPort, parentPort;
var dummyObj;
var DummyHandler = function()
{
this.onmessage = null;
var selfRef = this;
this.callHandler = function(arg)
{
if (typeof selfRef.onmessage === "function")
{
selfRef.onmessage(arg);
}
else
{
console.error("Message Handler not set");
}
};
};
function msgFromW(evt)
{
console.log(evt.data);
dummyObj.callHandler(evt);
}
self.addEventListener("message", function(evt) {
var data = evt.data;
if(data.msg === "connect")
{
otherPort = evt.ports[1];
otherPort.onmessage = msgFromW;
parentPort = evt.ports[0];
parentPort.postMessage({"msg": "connect"});
}
});
self.addEventListener("fetch", function(event)
{
var url = event.request.url;
var urlObj = new URL(url);
if(!isToBeIntercepted(url))
{
return fetch(event.request);
}
url = decodeURI(url);
var key = processURL(url).toLowerCase();
console.log("Fetch For: " + key);
event.respondWith(new Promise(function(resolve, reject){
dummyObj = new DummyHandler();
dummyObj.onmessage = function(e)
{
if(e.data.error)
{
reject(e.data.error);
}
else
{
var content = e.data.data;
var blob = new Blob([content]);
resolve(new Response(blob));
}
};
otherPort.postMessage({"msg": "content", param: key});
}));
});
港口的角色:
otherPort :与工人沟通
parentPort :与父页面的通信
在工人中,我有一个数据库说:
var dataBase = {
"file1.txt": "This is File1",
"file2.txt": "This is File2"
};
工作人员只根据服务工作人员发送的密钥提供正确的数据。 实际上这些将是非常大的文件。
我面临的问题如下:
This is File1
File1,因为最新的dummyObj用于file2.txt,但是worker首先发送file1.txt的数据。 我尝试直接创建iframe,并拦截其中的所有请求:
<html>
<head></head>
<body><iframe src="tointercept/file1.txt" ></iframe><iframe src="tointercept/file2.txt"></iframe>
</body>
</html>
一种方法是在创建iframe之前编写可以在worker中的IndexedDB中获取的所有文件。 然后在Service Worker中从索引的DB中获取它们。 但我不想保存IDB中的所有资源。 所以这种方法不是我想要的。
有没有人知道如何以其他方式完成我想要做的事情? 或者我正在做什么修复。
请帮忙!
UPDATE
我通过在一个全局队列中排队dummyObjs而不是一个全局对象来实现这一点。 在收到msgFromW
工作者的响应后,我从队列中弹出一个元素并调用其callHandler
函数。 但我不确定这是否是一个可靠的解决方案。 因为它假设一切都会按顺序发生。 这个假设是否正确?
我建议在promises中将服务工作者和Web worker之间的消息包装起来,然后将一个使用Web worker的数据解析的promise传递给fetchEvent.respondWith()
。
promise-worker
库可以为您自动执行此承诺包装,或者您可以手动执行此操作,使用此示例作为指南。
如果您使用的是promise-worker
,那么您的代码将类似于:
var promiseWorker = new PromiseWorker(/* your web worker */);
self.addEventListener('fetch', function(fetchEvent) {
if (/* some optional check to see if you want to handle this event */) {
fetchEvent.respondWith(promiseWorker.postMessage(/* file name */));
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.