sharedworker 是 html5 提供的跨标签页共享线程机制,同源页面通过相同脚本 url 创建实例即可复用,借助 port 通信实现状态同步;但 safari 长期不支持,需降级处理。

SharedWorker 是 HTML5 提供的一种 Web Worker 类型,它允许**不同浏览器标签页、iframe 甚至不同窗口**(同源前提下)共享同一个后台线程,从而实现跨页面的数据通信与状态同步。这和普通的 Worker(每个实例独占一个线程)有本质区别。
SharedWorker 的基本使用流程
要让多个标签页共用一个 SharedWorker,核心是:所有页面都通过相同的脚本路径创建 SharedWorker 实例,浏览器自动复用已存在的实例(同源 + 同脚本 URL)。
- 确保所有页面属于同一协议、域名和端口(即同源),否则 SharedWorker 不会被共享,甚至创建失败
- 编写一个独立的 JS 文件(如
shared-worker.js),作为 SharedWorker 的执行脚本 - 在每个页面中用
new SharedWorker('shared-worker.js')创建实例 —— 相同 URL 的多次调用会指向同一个底层线程 - 通过
worker.port建立通信通道,页面与 SharedWorker 之间使用postMessage()和onmessage交换数据
SharedWorker 脚本中的关键逻辑
SharedWorker 脚本运行在独立线程中,全局作用域是 self,不支持 window 或 document。它需监听 connect 事件来响应新页面连接:
// shared-worker.js
let portCount = 0;
let sharedState = { count: 0 };
self.onconnect = function(e) {
const port = e.ports[0];
portCount++;
port.postMessage({ type: 'init', data: { portCount, sharedState } });
port.onmessage = function(e) {
if (e.data.type === 'increment') {
sharedState.count++;
// 广播给所有已连接的端口
self.ports.forEach(p => p.postMessage({
type: 'update',
data: { count: sharedState.count }
}));
}
};
port.start(); // 必须调用 start() 才能收发消息(显式启用 MessageChannel)
};
注意:self.ports 是当前 SharedWorker 已连接的所有端口集合,可用于广播;每个 port 需手动调用 start()(若未设置 addEventListener('message', ...) 且未禁用自动启动)。
页面端的连接与通信示例
每个 HTML 页面只需创建 SharedWorker 并监听端口消息:
// index.html 中
const worker = new SharedWorker('shared-worker.js');
worker.port.onmessage = function(e) {
if (e.data.type === 'update') {
document.getElementById('counter').textContent = e.data.data.count;
}
};
worker.port.start(); // 启动端口
// 点击按钮触发共享计数器递增
document.getElementById('btn').onclick = () => {
worker.port.postMessage({ type: 'increment' });
};
打开多个该页面的标签页,点击任意一个页面的按钮,其余所有标签页的计数器都会实时更新 —— 这正是 SharedWorker 共享状态能力的体现。
常见问题与注意事项
SharedWorker 功能强大但使用时容易踩坑:
- Chrome 和 Edge 支持良好;Firefox 支持但默认启用,Safari **长期不支持 SharedWorker**(截至 Safari 17 仍无计划),需做降级处理(如 localStorage + storage 事件模拟)
- SharedWorker 实例在**最后一个端口关闭后不会立即销毁**,通常有几秒延迟;若需主动终止,可调用
worker.port.close(),但无法从外部强制 kill SharedWorker - 不能直接访问 DOM、
localStorage、indexedDB等非线程安全 API(但可通过self.indexedDB在 SharedWorker 中使用 indexedDB) - 调试 SharedWorker 较困难:Chrome DevTools 的 Application → Shared Workers 面板可查看运行状态和 console 输出;Firefox 需在
about:debugging中启用“显示系统工件”
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











