在 Main Thread
可以使用 new SharedWorker()
连接到指定 sharedWorker
。
而在 Shared Worker Thread
中,顶级 self
对象指向 SharedWorkerGlobalScope
,即共享 worker
全局作用域。
3-1.Main Thread
创建 SharedWorker
与 创建 Worker
的方式类似,唯一要注意的是:
SharedWorker
依赖端口port
通信;只有调用
port.start()
后,才能监听到message
事件。
js
// Main Thread
const sharedWorker = new SharedWorker('./sharedWorker.js')
sharedWorker.port.postMessage('Main Thread')
sharedWorker.port.addEventListener('message', (e) => {
console.log(e.data)
})
// 开启端口之后 端口才能监听到message事件
sharedWorker.port.start()
3-2.Shared Worker Thread
SharedWorkerGlobalScope
本身不支持 postMessage
。
需要先监听 connect
事件连接到端口 port
,然后再利用 port
通信。
js
// Shared Worker Thread
self.addEventListener('connect', e => {
const port = e.ports[0]
port.postMessage('Post Message from Shared Worker')
port.addEventListener('message', event => {
console.log('Shared Worker Thread', event.data)
})
port.start()
})
3-3.调试
SharedWorkerGlobalScope
的消息不会在默认的 console
控制台打印。
为了调试这部分代码的话,可以访问chrome://inspect。
另外,MDN
上的Simple Shared Worker也可以作为使用参考。
3-4.跨Tab数据通信
据笔者所知,跨 Tab
数据通信有两种方式:
可以利用
window.open
方法产生的opener
数据通信;本节的
SharedWorker
。
受到Redux SharedWorker的启发,可以将 SharedWorker
封装成公共函数,在各自数据通信的逻辑中调用即可。
假设有 Main Thread
、Iframe Thread
和 Shared Worker Thread
:
js
// Main Thread
import getSharedWorker from './worker.js'
const worker = getSharedWorker()
worker.port.postMessage('Post Message from Main Thread')
worker.port.addEventListener('message', e => {
console.log(e.data)
})
worker.port.start()
js
// Iframe Thread
import getSharedWorker from './worker.js'
const worker = getSharedWorker()
worker.port.postMessage('Post Message from Iframe Thread')
worker.port.addEventListener('message', e => {
console.log(e.data)
})
worker.port.start()
js
// Shared Worker Thread
// 为了保证响应式 可以将所有port存储到数组中,这样任一port变化时,都能作出反应。
const customrWorker = `
const workerList = []
self.addEventListener('connect', e => {
workerList.push(e.ports[0])
workerList.forEach(worker => {
worker.addEventListener('message', event => {
console.log(event.data)
})
worker.start()
})
})
`
export default function () {
return new SharedWorker(`data:application/javascript,${encodeURIComponent(customrWorker)}`, {
// type: 'module',
name: 'REDUX_SHARED_WORKER'
})
}