2015-06-14 101 views
3

是否可以从Web Worker调用共享工作者?如何从网络工作者调用共享工作者?

请给我举个例子。

就我而言,我有几个网络工作者,我需要在他们之间共享一个单身服务。

+0

可能重复的[在专用工作者中产生共享工作者](http://stackoverflow.com/questions/30741686/spawning-a-shared-worker-in-a-dedicated - 工作人员) –

+0

@MichalCharemza不适用于多个专职工作人员,因为'port'对象只能传送一次。 – levi

+0

对于每个专用工作者,您可以创建一个“新的SharedWorker”,并将端口对象传递给它。但是,我发现您正在寻找的答案与http://stackoverflow.com/a/30796101/1319998有点不同。删除我的近距离投票... –

回答

3

SharedWorker构造函数在WorkerGlobalScope中当前不可用,因此您将无法像在iframe或窗口中那样构造实例。

您可以做的是,为每位员工创建一个MessageChannel,并使用它在worker和sharedWorker之间进行通信。虽然这样做会抵消对实际SharedWorker的需求,因为您可以改为使用单个Worker

例子:

var numWorkers = 4; 
var sharedWorker = new Worker("worker-shared.js"); 

for(var i = 0; i < numWorkers; i++) { 
    var dedicatedWorker = new Worker("worker-dedicated.js"); 
    var channel = new MessageChannel(); 
    dedicatedWorker.postMessage({sharedWorkerPort: channel.port1}, [channel.port1]); 
    sharedWorker.postMessage({workerPort: channel.port2}, [channel.port2]); 
} 

Demo

+0

太棒了!非常感谢你! – Warlock

+0

请注意,根据http://caniuse.com/#feat=channel-messaging和https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel'MessageChannel'默认不支持Firefox –

+0

Firefox现在支持'MessageChannel'。 – levi

5

您可以在https://stackoverflow.com/a/30796101/1319998使用类似的技术。对于每个专用工作者,您可以创建一个共享工作者对象,指向相同的脚本,并将其端口传递给专用工作者。

请注意,对于相同的脚本URL,new SharedWorker(scriptUrl)不一定会创建一个新的共享工作线程:它只是创建一个新对象,允许您与共享工作线程通信,并且只创建线程本身已经不存在了。

作为示例,以下内容会创建2个Worker对象,每个对象创建一个单独的专用工作线程和2个对象,总共创建一个共享工作线程。共享工人的端口对象传递到专用工:然后

var sharedWorkerA = new SharedWorker("worker-shared.js"); 
sharedWorkerA.port.start(); 

var dedicatedWorkerA = new Worker("worker-dedicated.js"); 
dedicatedWorkerA.postMessage({sharedWorkerPort: sharedWorkerA.port, workerName: 'A'}, [sharedWorkerA.port]); 

var sharedWorkerB = new SharedWorker("worker-shared.js"); 
sharedWorkerB.port.start(); 

var dedicatedWorkerB = new Worker("worker-dedicated.js"); 
dedicatedWorkerB.postMessage({sharedWorkerPort: sharedWorkerB.port, workerName: 'B'}, [sharedWorkerB.port]); 

专用的工作人员可以在他们收到的端口对象发布消息:

self.onmessage = function(e) { 
    var workerName = e.data.workerName; 
    var sharedWorkerPort = e.data.sharedWorkerPort; 

    self.setInterval(function() { 
    sharedWorkerPort.postMessage('sent from dedicated worker ' + workerName); 
    }, 2000); 
}; 

而共享的工人可以接受其中:

var num = 0; 
self.onconnect = function(e) { 
    console.log('shared connect'); 
    var port = e.ports[0]; 

    port.onmessage = function(e) { 
    num++; 
    console.log('Received in shared worker: ', e.data); 
    console.log('Number of messaged received:', num); 
    }; 
}; 

我已经把一些额外的代码在那里只是为了证明确实是有一个实际的共享工作线程运行。你可以看到上面的工作在http://plnkr.co/edit/RcxxY2EDIcclUegC82wG?p=preview