shared worker 是跨标签页购物车同步的轻量级方案,通过独立脚本统一维护状态并广播变更;需同源注册、调用 port.start() 启动通信,worker 中用对象存状态、onconnect 监听连接、遍历 port 广播 sync 消息,页面按协议收发消息并更新 ui,辅以防抖、错误隔离和降级兼容机制。

Shared Worker 可以让多个页面共享同一个后台线程,是实现跨标签页购物车同步的轻量级方案。关键在于:所有页面通过同一个 SharedWorker 实例通信,由它统一维护商品数量状态,并主动广播变更。
一、创建并注册 Shared Worker
Shared Worker 需要独立的 JS 文件(如 cart-worker.js),且必须通过 new SharedWorker() 注册——注意路径需同源,且推荐使用相对路径或完整 URL(避免跨域失败)。
示例注册代码(在各页面中执行):
const cartWorker = new SharedWorker('cart-worker.js');
cartWorker.port.start(); // 必须调用 start() 启动端口通信
⚠️ 注意:若页面未调用 port.start(),消息无法收发;多个页面重复注册同一 worker,浏览器仍只启动一个实例。
二、在 Worker 中维护全局购物车状态
cart-worker.js 中用一个对象(如 cart = {})存储商品 ID → 数量映射,所有操作围绕它进行。利用 self.onconnect 监听页面连接,每个页面对应一个 port,可单独响应或广播。
常见操作逻辑:
-
初始化:首次连接时可加载本地存储的购物车数据(如
localStorage),但注意 Shared Worker 无法直接访问 localStorage,需由页面传入 -
增/删/改数量:接收页面发来的 {type: 'update', id: 'p100', delta: 1} 指令,更新
cart[id],过滤掉 0 或负值 -
广播同步:每次变更后,遍历所有已连接的
port,调用port.postMessage({type: 'sync', cart})
三、页面与 Worker 的双向通信约定
建议定义清晰的消息协议,避免类型混淆。例如:
- 页面 → Worker:
{type: 'get'}(请求当前状态)、{type: 'update', id, delta}(调整数量)、{type: 'reset'}(清空) - Worker → 页面:
{type: 'sync', cart: {...}, timestamp: Date.now()}(全量同步)、{type: 'error', msg}(异常提示)
页面中监听同步消息并更新 UI:
cartWorker.port.addEventListener('message', e => {
if (e.data.type === 'sync') {
updateCartUI(e.data.cart); // 自定义渲染函数
}
});
四、处理边界情况与增强健壮性
Shared Worker 本身不持久化,关闭所有页面后状态即丢失。生产环境建议补充以下机制:
-
页面加载时主动拉取:页面初始化后先发
{type: 'get'},Worker 返回当前 cart,再触发一次sync广播,确保新页面状态一致 -
防抖广播:高频操作(如连点加减)可对
sync广播加 100ms 防抖,避免频繁重绘 -
错误隔离:单个页面崩溃不会影响 Worker 运行,但需在
port.onclose中清理对应引用(虽非必须,利于调试) -
降级兼容:检测
SharedWorker是否支持(if (window.SharedWorker)),不支持时回退到 localStorage + storage 事件监听










