0

サービスワーカーを使用して私の要求を傍受し、同じ親ページから作成されたWebワーカーと通信して、フェッチ要求に対する応答を提供しています。 私は、ワーカーとサービスワーカーの間の直接通信にメッセージチャネルを使用しました。サービスワーカーが他のワーカーからデータを取得した後に取得する

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:親ページとのコミュニケーション

ここで私が書いた簡単なPOCであります労働者、私はデータベースがこれを言う:

var dataBase = { 
    "file1.txt": "This is File1", 
    "file2.txt": "This is File2" 
}; 

ワーカーは、サービスワーカーから送信されたキーに従って正しいデータを処理します。実際には、これらは非常に大きなファイルになります。

私はこれに直面しています問題は以下の通りです:

  1. 私はグローバルdummyObj、古いdummyObjを使用していますので、それ以上の年齢のonMessageが失われ、唯一、最新のリソースが受信したデータに対応しているので、 。
  2. 実際にfile2はThis is File1になります。最新のdummyObjはfile2.txtですが、ワーカーはまず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を作成する前にWorkerのIndexedDBにフェッチできるファイルその後、Service Workerでインデックス付きDBからそれらをフェッチします。しかし私はIDBのすべてのリソースを節約したくありません。だから、このアプローチは私が望むものではありません。

誰かが私が何か他の方法でやろうとしていることを達成する方法を知っていますか?それとも私がやっていることに修正がありますか?

助けてください!

UPDATE

私は、グローバルキューにdummyObjsキューイングの代わりに、グローバルオブジェクトを持つことで動作するようにこれを持っています。 msgFromWのワーカーからの応答を受け取ると、キューから要素がポップアップされ、callHandler関数が呼び出されます。 しかし、これが信頼できる解決策であるかどうかはわかりません。それはすべてが順番に起こると仮定しているからです。 この仮定は正しいですか?

答えて

-1

約束事でサービスワーカーとウェブワーカーの間を行き来するメッセージをラッピングしてから、ウェブワーカーからのデータで解決する約束をfetchEvent.respondWith()に渡すことをおすすめします。

promise-workerライブラリは、この約束のラッピングを自動化することも、手動で行うこともできます。this exampleを参考にしてください。あなたは私のコードが表示された場合、私は同じことを行っていない、

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

あなたがpromise-workerを使用していた場合、あなたのコードは次のようになりますか? – tapananand

+0

あなたは約束を使用していますが、メッセージコールバックの外部で管理されているグローバルキューは必要ありません。特定のコールバックに限定された約束に頼ることができます。 –

+0

私は約束を使用していますが、私は労働者からの応答を受け取ってダミーブブのonmessageを手動で呼び出します。だから私はキュー/マップがonmessageを呼び出すのを追跡する必要があります – tapananand

関連する問題