javascript - Service Worker 从另一个 Worker 获取数据后响应“获取”

标签 javascript indexeddb web-worker service-worker message-channel

我正在使用服务工作人员来拦截请求,并通过与 Web 工作人员(也是从同一父页面创建)通信来提供对获取请求的响应。 我使用消息 channel 在工作人员和服务工作人员之间进行直接通信。这是我写的一个简单的 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});
    }));
});

端口的 Angular 色:

otherPort:与worker通信

parentPort:与父页面通信

在工作人员中,我有一个数据库这样说:

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

Worker 只是根据 Service Worker 发送的 key 提供正确的数据。实际上,这些文件将非常大。

我面临的问题如下:

  1. 由于我使用的是全局 dummyObj,因此旧的 dummyObj 以及旧的 onmessage 都会丢失,并且只有最新的资源会使用收到的数据进行响应。
  2. 事实上,file2 获取这是 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 之前写入可以提取到工作线程中 IndexedDB 中的所有文件。然后在 Service Worker 中从索引数据库中获取这些内容。但我不想保存IDB中的所有资源。所以这种方法不是我想要的。

有人知道如何以其他方式完成我想做的事情吗?或者我正在做的事情有解决办法吗?

请帮忙!

更新

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

最佳答案

我建议将 Service Worker 和 Web Worker 之间传递的消息包装在 Promise 中,然后将使用来自 Web Worker 的数据进行解析的 Promise 传递给 fetchEvent.respondWith()

promise-worker库可以为您自动执行此 promise 包装,或者您可以使用 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 */));
  }
});

关于javascript - Service Worker 从另一个 Worker 获取数据后响应“获取”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38239233/

相关文章:

javascript - 为什么 Chrome 不允许 Web Worker 在 JavaScript 中运行?

javascript - 我可以生成一个 Web Worker 并将 JavaScript 函数从父级 "process"注入(inject)其中吗?

javascript - 如何在谷歌地图上显示自定义 DIV 元素作为标记?

javascript - XAMPP 不会更新 Web 源文件,直到它们在 Chrome 上提交给 Git

html - IndexedDB 是否适用于混合 android 应用程序?

javascript - 使用indexedDB时对象没有方法 "open"错误

javascript - 如何正确使用 v-if 和 v-for 嵌套对象 vue js

javascript - primefaces 密码控制,按 Enter 键调用 webflow 功能

javascript - IndexedDB 存储 250kB/s 流数据的性能问题

angularjs - Angular 服务和 Web Worker