0

我正在使用服务工作人员拦截对我的请求,并通过与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" 
}; 

工作人员只根据服务工作人员发送的密钥提供正确的数据。实际上这些将是非常大的文件。

我与此面临的问题如下:

  1. 由于我使用的是全球dummyObj,老dummyObj,因此旧的onMessage丢失,只有最新的资源回应与接收到的数据。
  2. 实际上,file2获得This is 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> 

这里是我得到的输出: enter image description here

一种方法可以写所有在创建iframe之前可以在工作人员中将其提取到IndexedDB中的文件。然后在服务工作人员从索引数据库中获取这些数据。但我不想保存IDB的所有资源。所以这种方法不是我想要的。

有没有人知道一种方法来完成我想以其他方式做的事情?或者有什么解决我在做什么。

请帮忙!

UPDATE

我有这个在全局队列中排队dummyObjs而不是有一个全局对象工作。在收到msgFromW中工作人员的响应后,我从队列中弹出一个元素并调用它的callHandler函数。 但我不确定这是否是可靠的解决方案。因为它假设一切都会按顺序发生。 这个假设是否正确?

回答

-1

我建议在承诺中包装服务工作者和web worker之间的消息传递,然后将承诺与web worker的数据一起解析为fetchEvent.respondWith()

promise-worker库可以自动执行此承诺,或者您可以手动完成,使用this example作为指导。

如果您使用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 */)); 
    } 
}); 
+0

如果你看到我的代码,我还没有做同样的事情? – tapananand

+0

您使用的是承诺,但不应该有任何需要在消息回调之外维护的全局队列。您可以依靠作用于特定回调的承诺。 –

+0

我正在使用promises,但我在接收工作人员的响应时手动调用dummyobj的onmessage。所以我需要队列/地图来跟踪谁的onmessage调用 – tapananand