使用 sharedworker 需要在主线程通过构造函数实例化,并监听 onconnect 事件以获取端口连接。在 worker 端,必须定义全局的 onconnect 处理器来接收来自不同页面的连接请求,并通过 port.start() 激活端口通信。这种方式允许一个 sharedworker 实例被多个同源标签页共享,实现跨页面状态同步或资源复用。

SharedWorker 与普通 Worker 的核心区别是什么
核心区别在于作用域和生命周期管理。普通 Worker 是专属于创建它的脚本的,一旦该脚本关闭或页面刷新,Worker 通常随之销毁(除非使用特定的持久化策略)。而 SharedWorker 是一个独立的全局单例,只要有一个同源页面持有其引用,它就会一直运行。这意味着多个页面可以连接到同一个 SharedWorker 实例,共享内存状态或后台任务结果。

// main.js (Page A)
const sw = new SharedWorker('worker.js');
sw.port.onmessage = (e) => console.log('From Worker:', e.data);
sw.port.start();
// worker.js
self.onconnect = function(e) {
const port = e.ports[0];
port.onmessage = function(e) {
// 处理来自任意页面的消息
port.postMessage('Hello from SharedWorker');
};
port.start();
};
如何处理多页面并发连接的消息路由
当多个页面同时连接时,每个连接都会获得一个独立的 MessagePort 对象。开发者需要在 Worker 内部维护这些端口的集合,或者根据业务逻辑将消息分发给特定的端口。关键在于,每个 port 都是独立的通信通道,互不干扰,但共享同一个 Worker 的执行上下文和全局变量。

// worker.js (Advanced Routing)
const ports = new Set();
self.onconnect = function(e) {
const port = e.ports[0];
ports.add(port);
port.onmessage = function(e) {
if (e.data.type === 'broadcast') {
// 广播给所有连接的页面
ports.forEach(p => p.postMessage({ type: 'update', content: e.data.payload }));
} else if (e.data.type === 'direct') {
// 仅回复当前发送者
port.postMessage({ type: 'reply', content: 'Received' });
}
};
port.onclose = function() {
ports.delete(port);
};
port.start();
};
SharedWorker 中如何确保数据一致性
由于所有连接共享同一个 JavaScript 执行环境,全局变量天然具备“共享状态”的特性。例如,在一个计数器场景中,任何页面修改全局变量,其他页面读取时都能得到最新值。然而,这种共享也带来了竞态风险,特别是在涉及异步操作时。建议通过消息协议明确状态变更的所有权,或使用原子性操作避免中间状态泄露。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











