SharedWorker 消息机制设计
核心概念
SharedWorker 的消息通信基于 Port(端口) 机制。每个连接到 Worker 的页面都会获得一个独立的端口,通过端口进行消息收发。
Tab 1 ←→ Port 1 ─┐
Tab 2 ←→ Port 2 ─┤→ SharedWorker(中转站)
Tab 3 ←→ Port 3 ─┘
text
Worker 端实现
// worker.js
const ports = new Map() // 使用 Map 存储端口和对应 ID
self.onconnect = (event) => {
const port = event.ports[0]
const clientId = Date.now().toString(36) + Math.random().toString(36).slice(2)
ports.set(clientId, port)
port.start()
// 通知新客户端其 ID
port.postMessage({ type: 'connected', clientId })
// 通知其他客户端有新连接
broadcast({ type: 'peer_joined', clientId }, clientId)
port.onmessage = (event) => {
const message = event.data
switch (message.type) {
case 'broadcast':
// 广播给所有其他客户端
broadcast({ type: 'message', from: clientId, data: message.data }, clientId)
break
case 'direct':
// 定向发送给指定客户端
const targetPort = ports.get(message.targetId)
if (targetPort) {
targetPort.postMessage({ type: 'message', from: clientId, data: message.data })
}
break
}
}
// 监听端口关闭
port.onclose = () => {
ports.delete(clientId)
broadcast({ type: 'peer_left', clientId })
}
}
function broadcast(message, excludeId) {
ports.forEach((port, id) => {
if (id !== excludeId) {
port.postMessage(message)
}
})
}
javascript
消息类型设计
| 消息类型 | 方向 | 说明 |
|---|---|---|
connected | Worker -> Client | 通知客户端连接成功并分配 ID |
peer_joined | Worker -> All | 有新客户端加入 |
peer_left | Worker -> All | 有客户端断开 |
broadcast | Client -> Worker | 请求广播消息 |
direct | Client -> Worker | 请求定向发送 |
message | Worker -> Client | 转发的消息内容 |
客户端连接
const worker = new SharedWorker('/worker.js')
const port = worker.port
port.start()
let myClientId = null
port.onmessage = (event) => {
const { type, clientId, data, from } = event.data
switch (type) {
case 'connected':
myClientId = clientId
break
case 'message':
console.log(`收到来自 ${from} 的消息:`, data)
break
case 'peer_joined':
console.log(`新客户端加入: ${clientId}`)
break
}
}
// 广播消息
function sendToAll(data) {
port.postMessage({ type: 'broadcast', data })
}
// 定向发送
function sendTo(targetId, data) {
port.postMessage({ type: 'direct', targetId, data })
}
javascript
这种设计使得 SharedWorker 成为一个灵活的消息中转站,支持广播和点对点两种通信模式。
↑