Ich verwende Service-Mitarbeiter, um Anfragen für mich abzufangen und die Antworten auf die Abrufanforderungen durch Kommunikation mit einem Web-Worker (ebenfalls von der gleichen übergeordneten Seite) bereitzustellen. Ich habe Nachrichtenkanäle für die direkte Kommunikation zwischen dem Arbeiter und Service-Arbeiter verwendet. Hier ist ein einfaches POC ich geschrieben habe:Service Worker reagiert auf Abruf nach dem Abrufen von Daten von einem anderen Mitarbeiter
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});
}));
});
Rollen der Ports:
anderer_Port: Kommunikation mit Arbeiter
parentPort: Kommunikation mit übergeordneten Seite
In der Arbeiter, ich habe eine Datenbank sagen:
Der Mitarbeiter liefert nur die korrekten Daten entsprechend dem vom Service-Mitarbeiter gesendeten Schlüssel. In Wirklichkeit werden dies sehr große Dateien sein.
Das Problem, das ich mit dieser bin vor ist die folgende:
- Da ich eine globale dummyObj verwenden, die ältere dummyObj und damit die ältere onmessage verloren geht und nur die letzte Ressource wird mit den empfangenen Daten reagiert .
- Tatsächlich erhält Datei2
This is File1
, weil das letzte dummyObj für file2.txt ist, aber der Arbeiter zuerst Daten für file1.txt sendet.
Ich habe versucht, durch ein iframe direkt erstellen und alle Anforderungen in ihm abgefangen werden:
<html>
<head></head>
<body><iframe src="tointercept/file1.txt" ></iframe><iframe src="tointercept/file2.txt"></iframe>
</body>
</html>
Hier ist, was ich als Ausgabe erhalten:
Ein Ansatz alle schreiben könnte die Dateien, die vor dem Erstellen des Iframes in den Worker in IndexedDB abgerufen werden konnten. Dann im Service Worker die aus der indizierten DB holen. Aber ich möchte nicht alle Ressourcen in IDB speichern. Also dieser Ansatz ist nicht was ich will.
Kennt jemand einen Weg, um zu erreichen, was ich auf eine andere Weise versuche? Oder gibt es eine Lösung für das, was ich tue?
Bitte Hilfe!
UPDATE
Ich habe dies durch die Warteschlangen dummyObjs in einer globalen Warteschlange stattdessen ein globales Objekt mit der Arbeit bekam. Und wenn ich die Antwort vom Arbeiter in msgFromW
empfange, knalle ich ein Element aus der Warteschlange und rufe seine callHandler
Funktion auf. Aber ich bin mir nicht sicher, ob dies eine zuverlässige Lösung ist. Da es annimmt, dass alles in der Reihenfolge auftreten wird. Ist diese Annahme richtig?
Wenn Sie meinen Code zu sehen, nicht ich das Gleiche getan? – tapananand
Sie verwenden Versprechungen, aber eine globale Warteschlange, die außerhalb der Nachrichtenrückrufe verwaltet wird, sollte nicht benötigt werden. Sie können sich auf Versprechungen verlassen, die auf den spezifischen Rückruf ausgerichtet sind. –
Ich verwende Versprechungen, aber ich rufe die Meldung von dummyobj manuell auf Antwort vom Arbeiter. Also brauche ich die Queue/Map, um zu verfolgen, wessen on-Nachricht zu rufen – tapananand