核心是将超16ms的纯计算任务剥离至worker线程:图像处理、大数据解析、加解密、矩阵运算等“一帧完不成”的任务必须迁移;需用transfer list零拷贝arraybuffer;须显式错误兜底与生命周期管理;应复用worker并设超时控制。
核心就一条:把超过 16ms 的纯计算任务,完整剥离到独立线程执行,主线程只留 ui 和交互逻辑。
哪些任务必须交给 Worker?
不是“慢才移”,而是“一帧内完不成”就得移。典型场景包括:
- 图像像素级处理(Canvas 滤镜、缩略图生成、水印叠加)
- 万行以上 CSV/JSON 解析、排序、聚合
- SHA-256、AES 加密解密、RSA 签名验签
- 大矩阵运算、物理模拟、素数筛、斐波那契递归(n > 40)
- 二维码生成、PDF 文本提取、OCR 前端预处理
通信不能只靠 postMessage(),要会“零拷贝”
传 10MB 图像数据,用普通 postMessage(data) 会触发深拷贝,序列化可能耗时上百毫秒——反而更卡。正确做法是转移 ArrayBuffer 所有权:
- 主线程:发送时加 transfer list → worker.postMessage({ buffer }, [buffer]),之后 buffer 自动变 null
- Worker 内:直接使用该 buffer,无复制开销
- 仅支持 ArrayBuffer、ImageBitmap、MessagePort 等可转移类型
- 避免传深层嵌套对象,优先用 TypedArray 或扁平结构
Worker 必须显式兜底错误和生命周期
Worker 报错默认静默,UI 可能一直转圈却毫无提示:
- 主线程创建时监听 worker.onerror,捕获加载失败或初始化异常
- Worker 脚本顶部加 self.onerror = e => self.postMessage({ type: 'error', error: e.message })
- 路径必须同源;Vite/Webpack 项目需声明 { type: 'module' },否则 import 失败
- 禁用 data: URL 或内联脚本创建方式,主流浏览器已拦截
别让 Worker 成为新瓶颈:复用 + 超时控制
每次 new Worker() 都有启动成本,高频小任务反复创建得不偿失:
- 用 Worker Pool 管理固定数量实例(建议 ≤ navigator.hardwareConcurrency)
- 每个 Worker 复用处理多个请求,靠 message.type 区分任务类型
- 主线程发任务时附带 timeout ID,Worker 超时未响应则主动终止并通知重试
- 长期空闲 Worker 可调用 worker.terminate() 释放资源










