在 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'
})
}