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