适合web worker的加密操作需满足纯计算且单次≥50ms,如aes-256大块数据加解密、rsa密钥生成/签名验签;sha-256短字符串哈希及后续同步ui更新则不适合。
直接把加密算法塞进 web worker,确实能守住动画帧率——前提是任务真被移出去了,且没在主线程留尾巴。
哪些加密操作适合丢给 Worker
不是所有加密都值得开线程。重点看两点:是否纯计算、单次耗时是否 ≥ 50ms。
- AES-256 加密/解密大块数据(比如 1MB 以上)——CPU 密集,无 DOM 依赖,适合
- RSA 密钥生成或签名验签(尤其 2048 位以上)——运算量大,阻塞主线程明显,适合
- SHA-256 对短字符串哈希(如密码字段)——本身几毫秒就完事,开 Worker 反而因启动+序列化更慢,不适合
- 调用 Web Crypto API 的 encrypt() 但后续立刻 document.querySelector 更新 UI ——Worker 算完了,主线程还在等渲染,掉帧照旧,不解决根本问题
传数据别传“活对象”,尤其避开 DOM 和函数
Worker 是干净沙盒,没有 document、window、Math(虽然部分 Math 方法可用,但不可靠),也不能访问闭包里的变量。
- 正确做法:把待加密的原始数据转成 ArrayBuffer 或 Uint8Array,用 transferable 方式发送。例如:
worker.postMessage({ data: buffer }, [buffer]) - 错误写法:传一个含
key: crypto.subtle.generateKey(...)的对象——Promise 不可克隆,会静默失败 - 别传
{ input: 'hello', algorithm: 'AES-GCM' }这种结构没问题;但别传{ fn: encrypt, key }——函数无法序列化
结果怎么回、UI 怎么动才不卡
加密完成只是第一步。主线程如何响应,决定动画是否真的流畅。
- Worker 内算完后,只发轻量结果,比如
{ success: true, encrypted: base64String, duration: 87 },别附带大数组或冗余元数据 - 主线程收到消息后,用 requestAnimationFrame 更新 UI,避免在 onmessage 回调里直接改 style 或 innerHTML(否则可能触发同步重排)
- 如果加密是动画流程中一环(比如点击按钮触发动画+加密),把动画启动和加密发起分开:先用 requestAnimationFrame 启动动画帧循环,再 postMessage 触发 Worker,两者不耦合
别忘了收尾,空转的 Worker 也会拖慢整体
一次加密任务结束,线程不该继续挂着。
- 主线程在确认收到 result 消息后,立即调用 worker.terminate()
- 或者让 Worker 自己在 postMessage 结果后执行 self.close(),更主动
- 不关的话,Worker 会长期占用内存,还可能干扰后续 Worker 调度,尤其在低端机上影响明显










