Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 服务工作者从另一工作者处获取数据后响应获取_Javascript_Indexeddb_Web Worker_Service Worker_Message Channel - Fatal编程技术网

Javascript 服务工作者从另一工作者处获取数据后响应获取

Javascript 服务工作者从另一工作者处获取数据后响应获取,javascript,indexeddb,web-worker,service-worker,message-channel,Javascript,Indexeddb,Web Worker,Service Worker,Message Channel,我使用服务工作者为我拦截请求,并通过与Web工作者(也从同一父页面创建)通信来提供对获取请求的响应。 我使用消息通道在工人和服务工人之间进行直接通信。下面是我写的一个简单的POC: var otherPort, parentPort; var dummyObj; var DummyHandler = function() { this.onmessage = null; var selfRef = this; this.callHandler = function(a

我使用服务工作者为我拦截请求,并通过与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});
    }));
});
港口的作用:

其他端口:与工人的通信

父端口:与父页面的通信

在worker中,我有一个数据库说:

var dataBase = {
    "file1.txt": "This is File1",
    "file2.txt": "This is File2"
};
工作者仅根据服务工作者发送的密钥提供正确的数据。实际上,这些将是非常大的文件

我面临的问题如下:

  • 由于我使用的是全局DummoBj,因此较旧的DummoBj和较旧的onmessage都会丢失,并且只有最新的资源会用接收到的数据进行响应
  • 事实上,file2获取
    这是File1
    ,因为最新的dummoybj是用于file2.txt的,但是worker首先发送File1.txt的数据
  • 我尝试直接创建iframe,其中的所有请求都被截获:

    <html>
    <head></head>
    <body><iframe src="tointercept/file1.txt" ></iframe><iframe src="tointercept/file2.txt"></iframe>
    </body>
    </html>
    
    
    
    以下是我得到的输出:

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

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

    请帮忙

    更新

    我通过在全局队列中对DummyObj进行排队来实现这一点,而不是使用全局对象。在
    msgFromW
    中接收到来自worker的响应时,我从队列中弹出一个元素,并调用其
    callHandler
    函数。
    但我不确定这是否是一个可靠的解决方案。因为它假设一切都会按顺序发生这个假设正确吗?

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

    该库可以为您自动完成此承诺包装,或者您也可以手动完成,作为指导

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

    我建议将服务工作者和web工作者之间传递的消息包装在Promission中,然后将使用web工作者的数据解析的Promission传递到
    fetchEvent.respondWith()

    该库可以为您自动完成此承诺包装,或者您也可以手动完成,作为指导

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

    您使用的是承诺,但不需要在消息回调之外维护全局队列。您可以依赖特定回调范围内的承诺。我使用的是承诺,但在收到工作者的响应时,我会手动调用dummyobj的onmessage。因此,我需要队列/映射来跟踪调用谁的onmessage我的观点是,如果您响应时承诺将消息请求/响应封装在其范围内,那么您就不再需要跟踪它,并且对竞争条件的担忧也就消失了。这一点似乎很难做到。希望你能帮忙。你试过图书馆吗?这看起来是一种简单的方法。您使用的是承诺,但不需要在消息回调之外维护全局队列。您可以依赖特定回调范围内的承诺。我使用的是承诺,但在收到工作者的响应时,我会手动调用dummyobj的onmessage。因此,我需要队列/映射来跟踪调用谁的onmessage我的观点是,如果您响应时承诺将消息请求/响应封装在其范围内,那么您就不再需要跟踪它,并且对竞争条件的担忧也就消失了。这一点似乎很难做到。希望你能帮忙。你试过图书馆吗?这看起来是一个简单的方法。