structuredClone() 无法拷贝 SyncManager,因其是不可序列化的平台对象,非数据容器;应通过 postMessage 传递 tag 等参数,由目标环境(如 Service Worker)重新获取 sync 实例。

不能使用 structuredClone() 拷贝包含 SyncManager 的对象。
SyncManager 不可序列化
SyncManager 是浏览器提供的 Web API 接口,用于注册后台同步任务(如 sync.register('my-tag'))。它属于“平台对象”(platform object),内部封装了与服务工作线程(Service Worker)生命周期和底层同步调度器的绑定关系。这类对象没有对应的可序列化表示,也不在 structuredClone() 的支持类型列表中(如 Window、Worker、SyncManager、PushManager 等均被明确排除)。
尝试拷贝会直接抛出 DataCloneError:
哪些值能被 structuredClone() 处理
structuredClone() 仅支持结构化克隆算法定义的类型,包括:
- 基本类型(
string、number、boolean、null、undefined、symbol(仅限同一 Realm)、bigint) - 普通对象、数组、Map、Set、Date、RegExp、ArrayBuffer、TypedArray、DataView、Blob、File、ImageBitmap、ImageData、DOM 节点(有限支持)
- 可转移对象(如
ArrayBuffer,需显式传入transfer选项)
SyncManager 不在其中 —— 它不是数据容器,而是行为接口,无法脱离运行时上下文存在。
实际开发中该怎么做
如果你需要在不同作用域(如主线程 ↔ Service Worker)间“传递同步能力”,不能拷贝 SyncManager 实例,而应:
-
在目标环境重新获取:Service Worker 中通过
navigator.serviceWorker.ready.then(reg => reg.sync)获取当前SyncManager;主线程中无法直接访问(因SyncManager仅在 Service Worker 全局作用域可用) - 只传递同步所需的参数:例如同步事件的 tag 名称(字符串)、重试策略(数字)、关联的业务数据(纯 JSON 可序列化对象)
-
用 postMessage + 消息驱动:主线程发送 { type: 'SYNC_REQUEST', tag: 'upload-queue', payload: [...] },Service Worker 收到后调用
self.registration.sync.register(tag)
替代深拷贝方案不适用
第三方深拷贝库(如 Lodash cloneDeep)同样无法处理 SyncManager —— 它们依赖属性遍历或 JSON 序列化,遇到不可枚举、不可遍历或宿主对象时会跳过、丢失或报错。强行包裹或 mock 会导致后续调用失败(如 sync.register() 报 InvalidStateError),因为底层绑定已丢失。











