sharedworker是同源多页面间共享状态与通信的核心机制,通过独立脚本实例充当中央消息中转站,需手动管理端口、状态广播与生命周期。

SharedWorker 是浏览器中实现多标签页间共享线程和状态的核心机制,它能让不同页面(同源)通过同一个 Worker 实例通信,从而避免轮询、WebSocket 或 localStorage + storage 事件等间接方案的缺陷。关键在于:所有页面连接到同一个 SharedWorker 实例,Worker 充当中央消息中转站,维护统一状态。
一、基础结构:注册与连接 SharedWorker
SharedWorker 必须由独立 JS 文件定义,不能内联。主页面通过 new SharedWorker() 连接,获取 port 进行双向通信。
示例:
worker.js(Worker 脚本):
let state = { count: 0, onlineUsers: new Set() };
const ports = new Set();
self.onconnect = (e) => {
const port = e.ports[0];
ports.add(port);
// 发送当前状态快照
port.postMessage({ type: 'INIT', data: state });
port.onmessage = (msg) => {
const { type, payload } = msg.data;
if (type === 'UPDATE') {
Object.assign(state, payload);
// 广播给所有连接的页面
ports.forEach(p => p.postMessage({ type: 'STATE_UPDATE', data: state }));
}
};
port.start(); // 必须调用 start() 启用端口
};
index.html 中连接:
const worker = new SharedWorker('worker.js');
const port = worker.port;
port.onmessage = (e) => {
const { type, data } = e.data;
if (type === 'INIT') {
console.log('初始状态:', data);
} else if (type === 'STATE_UPDATE') {
updateUI(data); // 更新页面 UI
}
};
port.start(); // 启动端口
port.postMessage({ type: 'UPDATE', payload: { count: 1 } }); // 触发更新
二、状态同步的关键细节
SharedWorker 本身不自动持久化状态,需自行管理;多个页面共用一个实例,但每个页面有独立 port,Worker 需显式广播变更。
-
必须手动调用
port.start():否则onmessage不触发,这是常见坑点 -
Worker 线程是单例:同源下无论打开多少个 tab,
new SharedWorker('x.js')总指向同一实例(除非脚本 URL 有差异,如带时间戳) -
页面关闭时自动断连:Worker 的
onclose不直接暴露,可通过port.onclose拦截,或监听ports集合变化(较难);更稳妥的做法是在页面卸载前主动发送离线通知 - 跨页面操作需幂等设计:比如 “+1” 操作应由 Worker 执行,而非让页面各自计算后提交,避免竞态
三、处理页面生命周期与可靠性
SharedWorker 在最后一个页面关闭后会自动终止,但有时需要感知“首次连接”或“最后离开”。可借助 self.clients(需在支持环境下)或简单计数模拟:
// 在 worker.js 中
let clientCount = 0;
self.onconnect = (e) => {
const port = e.ports[0];
clientCount++;
port.onmessage = (msg) => {
if (msg.data.type === 'HEARTBEAT') {
// 页面定期心跳,用于检测存活
port.lastActive = Date.now();
}
};
port.onclose = () => {
clientCount--;
if (clientCount === 0) {
// 清理资源,如重置 state(按需)
state = { count: 0 };
}
};
port.start();
};
页面端配合心跳:
// 每 5 秒发一次心跳
setInterval(() => {
port.postMessage({ type: 'HEARTBEAT' });
}, 5000);
四、实际可用的同步场景示例
适合 SharedWorker 的典型用例包括:
- 实时计数器:如“当前在线编辑人数”,所有 tab 增减都经 Worker 统一累加/减
- 播放控制同步:音乐/视频播放器在任一 tab 播放/暂停,其他 tab 自动响应
- 表单草稿共享:用户在 A 标签填写一半内容,切换到 B 标签仍能继续——Worker 缓存草稿并广播更新
- 权限状态广播:登录态变更(如 token 刷新、登出)由 Worker 统一推送,各页面即时响应
不复杂但容易忽略:SharedWorker 无法访问 DOM 和 window,所有逻辑必须纯 JS;调试靠 console.log 输出到 DevTools 的 “Console” 或 “Application → Service Workers” 面板(部分浏览器显示为 SharedWorker)。











