shared worker 可作为共享状态协调器实现多页面筛选条件同步:通过中心化 filterstate 管理、端口广播、防重逻辑、断连恢复及与后端联动,确保 ui 与数据请求一致。

Shared Worker 本身不能直接“自动同步筛选条件”,但它能作为中转枢纽,让多个 B 端页面在不互相感知的前提下,统一读写、广播和响应筛选状态。关键不是 Worker 自动做同步,而是你把它设计成一个“共享状态协调器”——所有筛选动作都经由它中转,自然就达成一致。
把筛选条件变成 Shared Worker 内的可管理状态
Worker 脚本里维护一个中心化对象(如 filterState = {}),所有页面发来的筛选变更(比如日期范围、部门下拉选中、状态标签勾选)都先提交给它,Worker 更新后,再主动推送给其他已连接的页面端口。
- 每个页面首次连接时发送
{ type: "init", clientId: "tab-xyz" },Worker 记录 port 映射 - 页面修改筛选项后,调用
port.postMessage({ type: "updateFilter", payload: { dateFrom: "2026-05-01", dept: "finance" } }) - Worker 收到后更新
filterState,再遍历所有 port(排除当前来源),转发完整状态:{ type: "syncFilter", data: filterState } - 各页面监听
port.onmessage,识别syncFilter类型,用其数据重置本地表单控件(如setDateRange()、setDeptSelect())
避免“循环同步”和状态抖动
多个页面同时操作筛选器时,容易出现 A → Worker → B → Worker → A 的无限回传。必须加一层防重逻辑:
- Worker 在转发前,记录本次更新的 originClientId,不向该 port 回推
- 页面收到
syncFilter后,不立即触发二次提交;可加if (isSyncingFromWorker) return;开关 - 对高频输入(如搜索框实时输入),Worker 可做简单节流(如 debounce 300ms),只同步最终值,而非每键一次
- 建议为每个筛选字段设置版本号或时间戳(
updatedAt: Date.now()),Worker 拒绝处理旧时间戳的更新请求
支持页面独立初始化与断连恢复
B 端系统常有页面跳转、局部刷新、新开 tab 等场景。新打开的页面需要“赶上进度”,而不是从空状态开始:
- 页面连接 Worker 后,先发
{ type: "requestCurrentFilter" } - Worker 收到即刻回复
{ type: "currentFilter", data: filterState } - 页面用该数据初始化 UI,并标记“已同步”,后续才开启监听 syncFilter 消息
- 页面关闭前发
{ type: "disconnect" },Worker 清理对应 port;但filterState不清空——它属于全局状态,存活于 Worker 生命周期内 - 若所有页面都关闭,Worker 终止;重启后状态丢失,此时需配合服务端持久化(如 localStorage 或 IndexedDB 存一份快照)
与后端联动:筛选变更即触发真实请求
同步 UI 只是第一步。真正价值在于——筛选条件一致后,所有页面发出的 API 请求参数也天然一致,便于审计、缓存复用和权限校验:
- Worker 收到
updateFilter后,可立即构造查询参数,调用fetch()获取最新列表数据(注意:Shared Worker 支持 fetch) - 拿到结果后,按
clientId分发:{ type: "data", list: [...], filter: {...} },各页面只渲染自己那份 - 也可将筛选条件透传给后端,在请求头或 query 中携带
x-sync-id,服务端据此判断是否为同一批筛选上下文,启用联合缓存策略 - 不推荐页面各自 fetch —— 容易因时间差导致数据不一致,且增加服务端压力










