shared worker 可通过监听 connect 事件并用 set 管理 port 实现连接追踪,需为每个 port 绑定 close 监听器及时清理,并提供广播或查询接口;注意 port.start() 必须调用、避免重复添加、不依赖 disconnect 事件。

Shared Worker 本身不直接暴露所有连接的端口(ports),但可以通过在 connect 事件中手动维护一个 ports 集合来实现对所有已连接页面的追踪。关键在于:每次有新页面连接时,将它的 port 存入集合;页面关闭或断开时,从集合中移除它。
监听 connect 事件并保存 port
Shared Worker 的全局作用域中,通过监听 connect 事件获取新连接的 MessagePort 对象。注意必须调用 port.start() 才能收发消息,且建议立即保存引用:
- 使用
Set存储活跃 port,避免重复和便于去重 - 每个 port 对应一个独立页面(即使同一页面多次 postMessage,也只产生一个 port)
- 保存前检查 port 是否已存在,防止意外重复添加
监听 port 的 close 事件以清理集合
每个 port 在对应页面卸载(如关闭标签页、刷新、导航离开)时会触发 close 事件。需为每个 port 绑定该事件监听器,在触发时从集合中删除它:
- 务必在
connect回调内为当前 port 添加close监听器 - 监听器中调用
ports.delete(port),确保及时释放引用 - 不要依赖
disconnect事件(它不标准,且不可靠)
提供统一接口供页面查询或广播
可在 Shared Worker 中暴露一个内部方法(例如通过特定 message type),让任意连接页面请求当前活跃连接数或全部 port 标识:
- 用
port.postMessage({ type: 'getActiveCount' })返回ports.size - 若需广播消息,遍历
ports.forEach(p => p.postMessage(...)),跳过已关闭的 port(port.close后再调用postMessage会静默失败,安全) - 可为每个 port 设置唯一 ID(如
port.id = crypto.randomUUID()),方便页面识别自身或做状态同步
注意事项与常见陷阱
Shared Worker 的生命周期独立于页面,但 port 引用必须显式管理。几个易忽略点:
- 页面刷新时,旧 port 会触发
close,新连接会建新 port —— 不会残留“僵尸 port” - 不能在
close回调里再调用port.close()(已关闭) - 若页面未调用
port.start(),则无法收发消息,但 port 仍存在于集合中,直到它自然关闭 - Shared Worker 被浏览器终止(如长时间闲置)时,整个脚本重启,集合清空 —— 此时无持久化机制











